HTML & CSS Essentials for AI-Assisted Development
Generate, Verify & Improve AI-Generated Markup
Course lectures and practices for JavaScript full‑stack web development with AI‑assisted workflows.
Welcome to Modern HTML/CSS
New Approach: This isn’t a comprehensive HTML/CSS tutorial. Instead, we’ll focus on the essential knowledge you need to verify and improve AI-generated code.
You already have AI tools! Use them to generate HTML/CSS, but you must understand what they create.
Learning Objectives
By the end of this session, you will be able to:
- ✅ Identify semantic HTML and why it matters
- ✅ Verify accessibility in AI-generated HTML
- ✅ Understand CSS selectors, specificity, and the box model
- ✅ Evaluate responsive design patterns
- ✅ Spot common issues in AI-generated markup
- ✅ Improve generated code for production quality
Part 1: HTML — Why Semantic HTML Matters
AI often generates <div>
soup — functionally correct but semantically wrong.
❌ What AI Might Generate
<div class="header">
<div class="nav">
<div class="nav-item">Home</div>
<div class="nav-item">About</div>
</div>
</div>
<div class="content">
<div class="article">
<div class="title">My Article</div>
<div class="text">Lorem ipsum...</div>
</div>
</div>
Problems:
- No semantic meaning
- Poor SEO
- Inaccessible to screen readers
- Harder to maintain
✅ Semantic Version
<header>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
</header>
<main>
<article>
<h1>My Article</h1>
<p>Lorem ipsum...</p>
</article>
</main>
Benefits:
- ✅ Clear document structure
- ✅ Better SEO
- ✅ Accessible
- ✅ Maintainable
Essential HTML5 Semantic Elements
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page Title</title>
</head>
<body>
<header> <!-- Page/section header -->
<nav> <!-- Navigation links -->
<!-- navigation links go here -->
</nav>
</header>
<main> <!-- Main content (ONE per page) -->
<article> <!-- Self-contained content -->
<section> <!-- Thematic grouping -->
<!-- section content -->
</section>
</article>
<aside> <!-- Sidebar/related content -->
<!-- aside content -->
</aside>
</main>
<footer> <!-- Page/section footer -->
<!-- footer content -->
</body>
</html>
- Multiple
<main>
elements — Only ONE allowed per page! - No heading hierarchy — Skipping from h1 to h4 confuses screen readers
- Generic
<div>
everywhere — Use semantic elements first, divs for styling only
Verification Checklist: Semantic HTML
When AI generates HTML, verify these critical points:
✅ Structure
✅ Accessibility
✅ SEO & Meta Tags
Live Demo: Fixing AI-Generated HTML
Scenario: AI generates a product card. Let’s review and improve it.
AI’s First Attempt
<div class="product-card">
<img src="phone.jpg">
<div class="product-name">iPhone 15</div>
<div class="price">$999</div>
<div class="button">Buy Now</div>
</div>
What’s wrong? (Identify with class)
- Missing alt text
- No semantic elements
- Button is a div (not interactive)
- No price semantics
Improved Version
<article class="product-card">
<img src="phone.jpg" alt="iPhone 15 in blue color">
<h2>iPhone 15</h2>
<p class="price">
<span class="sr-only">Price:</span>
<data value="999">$999</data>
</p>
<button type="button">Buy Now</button>
</article>
Improvements:
- ✅
<article>
(self-contained product) - ✅
<h2>
(semantic heading) - ✅
<data>
element (machine-readable price) - ✅ Real
<button>
(keyboard accessible) - ✅ Alt text (descriptive)
- ✅ Screen-reader text for “Price”
Add a utility class for visually-hidden text used for assistive technologies (used above as .sr-only
).
.sr-only {
position: absolute !important;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
: rect(0, 0, 0, 0);
clipwhite-space: nowrap;
border: 0;
}
Use .sr-only
for labels or helper text that should be read by screen readers but not shown visually.
Instead of: “Create a product card”
Try: “Create a semantic HTML product card with proper accessibility. Include article element, heading, alt text for images, and a real button element.”
ARIA, Landmarks & Skip Links
Landmarks and ARIA help screen readers navigate your page. Prefer native semantic elements (nav, main, header, footer, aside) first — use ARIA only when semantics can’t be expressed with native HTML.
<!-- Skip link for keyboard users -->
<a class="skip-link" href="#main">Skip to content</a>
<!-- Nav with accessible name -->
<nav aria-label="Primary navigation">
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
<!-- Use aria-hidden for decorative elements -->
<svg aria-hidden="true" focusable="false">...</svg>
Notes:
- Skip links should be first focusable element and become visible on :focus.
- Prefer
aria-label
or a visible heading inside landmarks to give assistive tech a name. - Avoid adding ARIA roles that duplicate native elements (don’t add
role="navigation"
to a<nav>
unless you need to override semantics). - Use
aria-hidden="true"
for purely decorative content so screen readers ignore it.
Prompting tip for LLMs: “Return semantic HTML with ARIA where necessary. Include a skip-link and explicit aria-labels on landmarks. Explain any ARIA you add and why native semantics couldn’t cover it.”
Responsive Images & Lazy-loading
When AI generates image markup it often forgets responsive sources, width/height, and lazy-loading : this harms performance and causes layout shifts.
Basic responsive img
with srcset
/sizes
and lazy loading:
<img
src="/images/phone-800.jpg"
srcset="/images/phone-400.jpg 400w, /images/phone-800.jpg 800w, /images/phone-1200.jpg 1200w"
sizes="(max-width: 600px) 100vw, 50vw"
width="800" height="600"
loading="lazy"
decoding="async"
alt="iPhone 15 in blue color">
Use <picture>
for format selection or art-direction (e.g., WebP fallback or different crops):
<picture>
<source type="image/webp" srcset="/images/phone-800.webp 800w, /images/phone-1200.webp 1200w" sizes="(max-width:600px) 100vw, 50vw">
<img src="/images/phone-800.jpg" srcset="/images/phone-800.jpg 800w, /images/phone-1200.jpg 1200w" sizes="(max-width:600px) 100vw, 50vw" loading="lazy" width="800" height="600" alt="iPhone 15 in blue color">
</picture>
Best practices to include in verification:
- Always include
alt
(oralt=""
for purely decorative images) and a sensiblewidth
/height
or CSS aspect-ratio to avoid layout shift. - Use
loading="lazy"
for non-critical images,decoding="async"
for faster paint. - Prefer
srcset
/sizes
or<picture>
for large images so browsers select appropriate resources. - Validate generated image paths and ensure optimized assets exist (AI may invent filenames).
Prompting tip for LLMs: “Generate image markup with srcset, sizes, width/height, loading=”lazy”, and a brief note about expected image file names and sizes. If the image is decorative, set alt=“” and aria-hidden as needed.”
Part 2: CSS Essentials for Verification
You must understand these to verify AI-generated CSS:
- Selectors — How to target elements
- Specificity — Which styles win when there’s conflict
- Box Model — How spacing works
CSS Basic Selectors
/* Element selector */
color: blue; }
p {
/* Class selector (most common) */
.highlight { background: yellow; }
/* ID selector (use sparingly) */
#header { position: fixed; }
/* Attribute selector */
[type="text"] { border: 1px solid gray; }
CSS Combinators
/* Descendant (any level) */
.card p { margin: 0; }
/* Direct child only */
.card > p { margin: 0; }
/* Adjacent sibling */
+ p { font-weight: bold; }
h2
/* General sibling */
~ p { color: gray; } h2
Pseudo-classes (State-based)
/* User interactions */
:hover { color: red; }
a:focus { outline: 2px solid blue; }
a:active { transform: scale(0.95); }
button
/* Position-based */
:first-child { font-weight: bold; }
li:last-child { margin-bottom: 0; }
li:nth-child(odd) { background: #f0f0f0; } li
CSS Specificity
Specificity determines which style wins when multiple rules target the same element.
Specificity Hierarchy (from weakest to strongest):
- Element selectors (div, p, h1)
- Class selectors (.card, .btn)
- Attribute selectors and pseudo-classes ([type=“text”], :hover)
- ID selectors (#header)
- Inline styles (style=“…”)
- !important (avoid in production — overrides everything)
Example: Which style wins?
CSS rules:
/* Specificity: (1 element) */
color: blue; }
p {
/* Specificity: (1 class) - WINS! */
.text { color: red; }
/* Specificity: (1 class + 1 element) - WINS OVER .text! */
.text { color: green; }
p
/* Specificity: (1 ID) - WINS OVER EVERYTHING! */
#intro { color: purple; }
HTML example:
<p class="text" id="intro">What color is this?</p>
<!-- Answer: PURPLE (ID has highest specificity) -->
AI might generate:
#button1 { background: blue; }
#button2 { background: blue; }
#button3 { background: blue; }
Problem: Not reusable, high specificity
Better approach:
.btn-primary { background: blue; }
The Box Model: Understanding Spacing
Every element is a box with 4 layers:
┌─────────────────────────────────┐
│ MARGIN (transparent) │
│ ┌───────────────────────────┐ │
│ │ BORDER │ │
│ │ ┌─────────────────────┐ │ │
│ │ │ PADDING │ │ │
│ │ │ ┌───────────────┐ │ │ │
│ │ │ │ CONTENT │ │ │ │
│ │ │ │ (text, img) │ │ │ │
│ │ │ └───────────────┘ │ │ │
│ │ └─────────────────────┘ │ │
│ └───────────────────────────┘ │
└─────────────────────────────────┘
Box Model Properties
.box {
/* Content size */
width: 200px;
height: 100px;
/* Spacing inside the border */
padding: 20px; /* All sides */
padding: 10px 20px; /* vertical | horizontal */
padding: 10px 20px 30px; /* top | horizontal | bottom */
/* Border */
border: 2px solid black;
/* Spacing outside the border */
margin: 20px;
margin: 0 auto; /* Center horizontally */
}
Box-Sizing: Critical for Layout
/* Default behavior (confusing!) */
.box {
width: 200px;
padding: 20px;
border: 2px solid;
/* Total width = 200 + 20*2 + 2*2 = 244px! */
}
/* Modern best practice (include padding/border in width) */
* {
box-sizing: border-box;
}
.box {
width: 200px;
padding: 20px;
border: 2px solid;
/* Total width = 200px (padding and border included) */
}
/* At the top of your CSS file */
*, *::before, *::after {
box-sizing: border-box;
}
AI often forgets this! Add it manually.
CSS Verification Checklist
When AI generates CSS, check:
✅ Selectors
✅ Layout
✅ Accessibility
Part 3: Responsive Design Patterns - Mobile-First Approach
Modern standard: Design for mobile, enhance for desktop.
Mobile-First Media Queries
/* Base styles (mobile) */
.container {
width: 100%;
padding: 10px;
}
/* Tablet and up (min-width = mobile-first) */
@media (min-width: 768px) {
.container {
max-width: 720px;
margin: 0 auto;
}
}
/* Desktop and up */
@media (min-width: 1024px) {
.container {
max-width: 960px;
} }
Watch for max-width
media queries (desktop-first):
/* Desktop styles (default) */
.sidebar { width: 300px; }
/* Then mobile */
@media (max-width: 768px) {
.sidebar { width: 100%; }
}
Ask AI to rewrite as mobile-first!
Flexbox: The Modern Layout Tool
Use Flexbox for one-dimensional layouts (rows or columns).
/* Parent container */
.flex-container {
display: flex;
flex-direction: row; /* or column */
justify-content: center; /* align on main axis */
align-items: center; /* align on cross axis */
gap: 20px; /* spacing between items */
}
/* Child items */
.flex-item {
flex: 1; /* Grow to fill space equally */
}
Common Patterns
/* Horizontal navigation */
nav {display: flex;
gap: 20px;
}
/* Centered content */
.hero {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
/* Card layout (wrap on small screens) */
.cards {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.card {
flex: 1 1 300px; /* grow | shrink | basis */
}
CSS Grid: Two-Dimensional Layouts
Use Grid for complex two-dimensional layouts.
Basic Grid Pattern
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr); /* 3 equal columns */
gap: 20px;
}
/* Responsive grid (auto-fit) */
.responsive-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
}
- Flexbox: Navigation bars, button groups, simple card layouts
- Grid: Page layouts, complex card grids, dashboard layouts
- Both: Nest Flexbox inside Grid cells!
Tailwind CSS: AI’s Favorite Framework
Traditional CSS
<style>
.card {
padding: 1.5rem;
background: white;
border-radius: 0.5rem;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}</style>
<div class="card">Content</div>
Tailwind = Utility-first CSS framework
Instead of writing CSS, use pre-built classes:
Tailwind Approach
<div class="p-6 bg-white rounded-lg shadow-md">
Content</div>
Tailwind pros & cons
Pros:
- ✅ Fast prototyping (AI loves this!)
- ✅ No naming decisions
- ✅ Responsive utilities built-in
- ✅ Consistent design system
Cons:
- ❌ HTML gets cluttered
- ❌ Learning curve for utilities
- ❌ Harder to scan visually
Essential Tailwind Classes
Spacing (m=margin, p=padding, numbers = 4px units)
<div class="m-4"> margin: 1rem (16px)
<div class="p-6"> padding: 1.5rem (24px)
<div class="mx-auto"> margin-left/right: auto (center)
<div class="mt-2"> margin-top: 0.5rem
Layout
<div class="flex items-center justify-between">
<div class="grid grid-cols-3 gap-4">
<div class="w-full md:w-1/2"> width: 100% on mobile, 50% on md+
Typography
<h1 class="text-3xl font-bold text-gray-900">
<p class="text-base text-gray-600 leading-relaxed">
Colors (gray, red, blue, green, etc. with shades 50-900)
<div class="bg-blue-500 text-white">
<div class="bg-gray-100 text-gray-900">
<div class="hover:bg-blue-600"> darker blue on hover
Responsive Prefixes (sm, md, lg, xl, 2xl)
<div class="text-sm md:text-base lg:text-lg">
<!-- Small on mobile, base on tablet, large on desktop -->
AI + Tailwind = Perfect Match
When prompting AI for Tailwind:
"Create a product card using Tailwind CSS with:
- White background with shadow
- Padding and rounded corners
- Responsive (full width on mobile, 1/3 on desktop)
- Hover effect on image"
AI will generate Tailwind classes correctly most of the time!
Part 4: Common AI Mistakes & How to Fix Them
🚩 Problem 1: Inline Styles Everywhere
<!-- ❌ AI might generate -->
<div style="background: blue; padding: 20px; margin: 10px;">
<p style="color: white; font-size: 16px;">Text</p>
</div>
Why bad? Not reusable, hard to maintain, poor separation of concerns
Fix: Use classes
<!-- ✅ Better -->
<div class="card">
<p class="card-text">Text</p>
</div>
<style>
.card { background: blue; padding: 20px; margin: 10px; }
.card-text { color: white; font-size: 16px; }
</style>
🚩 Problem 2: No Alt Text or Generic Alt
<!-- ❌ AI might generate -->
<img src="product.jpg">
<img src="product.jpg" alt="image">
<img src="product.jpg" alt="product image">
Why bad? Screen readers can’t describe the image
Fix: Descriptive alt text
<!-- ✅ Better -->
<img src="product.jpg" alt="iPhone 15 Pro in titanium blue finish">
Prompt fix: “Ensure all images have descriptive alt text explaining what’s shown”
🚩 Problem 3: Fake Buttons (Divs with Click Handlers)
<!-- ❌ AI might generate -->
<div class="button" onclick="buy()">Buy Now</div>
Why bad? - Not keyboard accessible (can’t Tab to it) - No focus indicator - Screen readers don’t announce it as a button - No Enter/Space key support
Fix: Real button elements
<!-- ✅ Better -->
<button type="button" onclick="buy()">Buy Now</button>
🚩 Problem 4: CSS Without box-sizing
/* ❌ AI often forgets */
.card {
width: 300px;
padding: 20px;
border: 2px solid;
/* Actual width = 344px! */
}
Fix: Add box-sizing globally
/* ✅ Add at top of CSS file */
*, *::before, *::after {
box-sizing: border-box;
}
🚩 Problem 5: No Focus Styles
/* ❌ AI might only style hover */
:hover {
buttonbackground: darkblue;
}
Why bad? Keyboard users can’t see where they are
Fix: Always include focus styles
/* ✅ Better */
:hover,
button:focus {
buttonbackground: darkblue;
}
:focus {
buttonoutline: 2px solid blue;
outline-offset: 2px;
}
🚩 Problem 6: Hardcoded Pixel Values Everywhere
/* ❌ AI loves px */
.container {
width: 1200px;
padding: 20px;
margin: 30px;
}
Why bad? Not responsive, doesn’t scale with user’s font preferences
Fix: Use relative units
/* ✅ Better */
.container {
max-width: 75rem; /* 1200px at default font size */
padding: 1.25rem; /* Scales with font size */
margin: 0 auto; /* Center horizontally */
}
Unit guide:
rem
— Relative to root font size (best for spacing)em
— Relative to parent font size (good for padding inside text)%
— Relative to parent element (good for widths)vw/vh
— Relative to viewport (good for full-screen sections)
Your Verification Workflow
Every time AI generates HTML/CSS:
Step 1: Read & Understand (Don’t just copy!)
- What is this code trying to do?
- Are there semantic elements or just divs?
Step 2: Check Semantics
Step 3: Check Accessibility
Step 4: Check CSS Quality
Step 5: Test in Browser
Summary & Key Takeaways
- Semantic HTML first — Then style with CSS
- Accessibility is not optional — Alt text, labels, focus states
- Mobile-first responsive — Start small, enhance for large screens
- AI generates, you verify — Never copy-paste without understanding
- Test in real browsers — DevTools + keyboard navigation + Lighthouse
Prompt Templates for Practice
Now you try! Use these prompts with your AI tool of choice.
For HTML Generation
Create semantic HTML for a product review card with:
- Article element as container
- Product image with descriptive alt text
- Heading for reviewer name
- Star rating (5 stars, accessible)
- Review text paragraph
- Date element with machine-readable format
- Helpful/Not helpful buttons (real button elements)
Ensure proper accessibility with ARIA labels where needed.
For Tailwind CSS Styling
Style the review card using Tailwind CSS with:
- White background with subtle shadow
- Rounded corners and padding
- Responsive layout (full width on mobile, 1/3 on desktop)
- Hover effect (slight shadow increase)
- Focus states for buttons
- Mobile-first approach with sm:, md:, lg: breakpoints
For Verification
Review this HTML/CSS code for:
- Semantic HTML correctness
- Accessibility issues (alt text, labels, focus states)
- CSS best practices (box-sizing, relative units)
- Responsive design patterns
- Any potential problems
Suggest specific improvements with code examples.
Let’s Build! 🚀
You now have the knowledge to:
- Generate HTML/CSS with AI
- Verify it’s semantic and accessible
- Improve it for production quality
- Test it properly in browsers