CSS Essentials  •  07/09/2026
Using the Conversation Quests Stylesheets as Reference — Part 2 of 3

CSS Essentials

10 properties and patterns that explain 80% of what you see on screen — what to understand, what to let AI handle.

Every rule in this guide came from the stylesheets powering this series — convQuestPosterStyles.css, convQuest1Styles.css, and the shared tnt-base-styles.css. Real rules from working pages.

CSS has hundreds of properties. These 10 cover the core mental models. Once you understand how CSS thinks about color, spacing, layout, and responsiveness, everything else is pattern recognition. That’s exactly where AI becomes useful — it fills in the patterns once you know what to ask for.

The 10 Properties

All 10 appear in the Conversation Quests Poster stylesheet. Open the poster and its stylesheet side by side while you read.

01 color background-color rgba()

Color & Background Color

color sets the text color of an element and its children. background-color fills the element’s box. rgba(r, g, b, a) adds an opacity channel: a = 0 is fully transparent; a = 1 is fully opaque. The dark-theme pages in this series use rgba() throughout so background layers remain partially transparent and blend with what’s behind them.

In the Poster CSS
body {
    background-color: #0d0818;
    color: rgba(255, 255, 255, 0.88);
}

.poster-card {
    background: rgba(8, 5, 20, 0.82);
}

.poster-qs li {
    color: rgba(255, 255, 255, 0.87);
}
⚡ Vibe Coder’s Note

You understand: The fourth value in rgba() is opacity. A card with rgba(8,5,20,0.82) is 82% opaque — enough to make text readable while letting the background image glow through.

AI handles: Choosing color values. Review AI’s contrast choices — white text on a dark background needs at least a 4.5:1 contrast ratio (WCAG AA). Ask AI to "ensure accessible contrast."

02 padding margin box-sizing

The Box Model

Every element is a box. padding is the space inside the border between the content and the edge. margin is the space outside the border between this element and its neighbors. They look similar but behave completely differently when backgrounds and borders are involved. The shorthand padding: 2rem 2.6rem means "2rem top/bottom, 2.6rem left/right."

In the Poster CSS
.poster-card {
    padding: 2.6rem 2.6rem 2rem;
    /* top 2.6rem, left/right 2.6rem, bottom 2rem */
}

.poster-tier {
    padding: 0.9rem 1rem 0.85rem;
    border: 1px solid rgba(255, 255, 255, 0.09);
    border-radius: 0 10px 10px 0;
}
⚡ Vibe Coder’s Note

You understand: Padding grows the colored background; margin does not. If an element’s background seems too large or small, it’s usually a padding issue. If elements are too close or too far apart, it’s usually margin.

AI handles: All shorthand calculations. When you say "give this card generous breathing room," AI writes appropriate padding values.

03 font-family font-size: clamp() line-height

Typography

font-family names the typeface (or a fallback chain). font-size: clamp(min, preferred, max) is the modern responsive approach: never smaller than min, never larger than max, scaling fluidly to preferred (usually a viewport-relative value like 4vw). line-height without a unit (e.g., 1.45) is always relative to the current font size — this is always the correct approach.

In the Poster CSS
:root {
    --playfair: 'Playfair Display', Georgia, serif;
    --nunito:   'Nunito', 'Inter', Arial, sans-serif;
}

.poster-title {
    font-family: var(--playfair);
    font-size: clamp(1.6rem, 4vw, 2.5rem);
    line-height: 1.1;
}

.poster-qs li {
    font-size: 0.79rem;
    line-height: 1.45;
}
⚡ Vibe Coder’s Note

You understand: clamp() eliminates the need for a separate media query just for font size. The three values are: minimum, preferred (viewport-based), maximum. AI uses it correctly when you ask for "responsive font sizing."

AI handles: Font stacks and clamp() values. The fallback chain (Georgia, serif) is what renders if the Google Font fails to load — AI always includes it.

04 display: flex align-items justify-content gap

Flexbox Layout

display: flex turns an element into a flex container and its children into flex items. justify-content distributes items along the main axis (horizontal by default). align-items aligns them on the cross axis (vertical by default). When flex-direction: column is set, those axes flip. The #1 flexbox mistake: using justify-content when you mean align-items, or vice versa.

In the Poster CSS
.poster-tier-header {
    display: flex;
    align-items: center;
    gap: 0.55rem;
}

.poster-tips-bar {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.3rem 2.2rem; /* row-gap / column-gap */
}

.poster-card {
    display: flex;
    flex-direction: column; /* stack header, grid, tips vertically */
}
⚡ Vibe Coder’s Note

You understand: To center something both horizontally and vertically, use display: flex; align-items: center; justify-content: center on the parent. This is the most commonly asked-for flexbox pattern.

AI handles: All flexbox syntax. Tell AI what you want to achieve visually ("center this element," "place these side by side with a gap") and it produces correct flexbox rules.

05 --variable: value var(--variable)

CSS Custom Properties

CSS custom properties (often called "variables") store a value in one place and reference it everywhere. Change it once in :root and every element that uses it updates. The poster uses a two-layer pattern: global palette tokens in :root, then component-scoped tokens set by modifier classes — the same technique large design systems use for theming.

In the Poster CSS
/* Layer 1: global palette, defined once */
:root {
    --cq-curiosity: #5B9BD5;
    --cq-vision:    #D4A830;
}

/* Layer 2: modifier class sets a component-scoped token */
.poster-tier--curiosity {
    --tier-color: var(--cq-curiosity);
}

/* Layer 3: base rule reads the token */
.poster-tier {
    border-left: 3px solid var(--tier-color, rgba(255,255,255,0.3));
}
⚡ Vibe Coder’s Note

You understand: If the same color appears hardcoded in more than one place in AI output, ask AI to extract it into a custom property. The second value in var(--x, fallback) is a default used if --x isn’t set.

AI handles: Creating and consuming custom properties. Review whether AI is using them consistently — it sometimes creates variables and then uses hardcoded values elsewhere in the same file.

06 background: gradient url() background-size: cover

Multi-Layer Background

The background shorthand accepts multiple comma-separated layers: the first listed is rendered on top. In the poster, a gradient overlay comes first so it darkens the background image just enough for white text to remain readable — regardless of how bright the image is. background-color at the end is the fallback rendered if both layers fail to load.

In the Poster CSS
/* Poster section: image only, solid color fallback */
#posterSection {
    background: url('../images/talkingPic1AExpress.jpg')
                center / cover no-repeat;
    background-color: #0d0818;
}

/* Hero: gradient overlay ON TOP of image */
#hero {
    background:
        linear-gradient(160deg, rgba(20,8,45,0.40), rgba(8,4,22,0.20)),
        url('../images/convQuestHero.png') center / cover no-repeat;
    background-color: #100828;
}
⚡ Vibe Coder’s Note

You understand: First layer = top. The overlay gradient must come before the image URL, not after. When the image file is missing, the browser falls through to background-color. Design for that case.

AI handles: The multi-layer syntax. Tell AI "add a semi-transparent dark gradient over the background image so white text is always readable" and it produces the correct layer order.

07 border border-radius overflow: hidden

Border, Radius & Overflow

border sets all four sides at once; border-left overrides just the left (later rules win). border-radius: 0 10px 10px 0 rounds only the right corners — shorthand goes clockwise: top-left, top-right, bottom-right, bottom-left. The critical partner: overflow: hidden makes child elements respect the parent’s rounded corners. Without it, children can visually escape the rounded shape.

In the Poster CSS
.poster-card {
    border: 1.5px solid rgba(212, 168, 48, 0.35);
    border-radius: 16px;
    overflow: hidden; /* keeps .poster-stripe inside the corners */
}

.poster-tier {
    border: 1px solid rgba(255, 255, 255, 0.09);
    border-left: 3px solid var(--tier-color); /* overrides left side */
    border-radius: 0 10px 10px 0;             /* right corners only */
}
⚡ Vibe Coder’s Note

You understand: overflow: hidden is the secret ingredient when rounded corners don’t clip children. Any time a child element bleeds outside rounded corners, add overflow: hidden to the parent.

AI handles: Border shorthand and radius values. May forget overflow: hidden when you need it — specifically ask for it when a child element should clip to the parent’s border-radius.

08 transition @keyframes animation

Transitions & Animations

transition animates a property change smoothly when it’s triggered externally (e.g., by JavaScript swapping a class). animation runs independently, triggered by adding the class that references an @keyframes rule. The distinction: transitions react to changes; animations run on their own. Always prefer animating opacity and transform — they skip layout recalculation and run on the GPU.

In the Poster CSS (and convQuest1Styles.css)
/* Transition: smooth when border-color changes */
.poster-card {
    transition: border-color 0.4s ease;
}

/* Animation: runs when .animating class is applied */
@keyframes cardReveal {
    from { opacity: 0; transform: translateY(18px) scale(0.96); }
    to   { opacity: 1; transform: translateY(0)    scale(1); }
}
.draw-card.animating {
    animation: cardReveal 0.50s cubic-bezier(0.22, 1, 0.36, 1) both;
}
⚡ Vibe Coder’s Note

You understand: animation-fill-mode: both keeps the element in its final @keyframes state after the animation ends. Without it, elements snap back to their starting position. The shorthand value both combines forwards and backwards.

AI handles: Writing @keyframes and cubic-bezier values. Tell AI the character of the animation ("snappy," "gentle," "bouncy") and it picks appropriate easing.

09 position: sticky position: absolute z-index

The Position System

Four values, four behaviors. static (default) follows normal flow. relative nudges the element and creates a positioning context for absolute children. absolute pops out of flow and positions relative to the nearest non-static ancestor. fixed anchors to the viewport. sticky behaves normally until a threshold, then sticks. The most important rule: an absolutely-positioned element needs a position: relative parent to position correctly.

In the Series (Bootstrap’s .sticky-top equivalent)
/* Bootstrap's .sticky-top applies: */
#mainNav {
    position: sticky;
    top: 0;          /* sticks to the top of the viewport */
    z-index: 1020;   /* stays above scrolling content */
}

/* Absolute child inside a relative parent: */
.poster-card { position: relative; }  /* creates context */
.poster-card::before {
    position: absolute;
    inset: 0;           /* shorthand: top right bottom left = 0 */
    pointer-events: none;
}
⚡ Vibe Coder’s Note

You understand: If an absolutely-positioned element is appearing in the wrong place, check whether its parent has position: relative. That’s the fix 90% of the time.

AI handles: The correct position value for each use case. If the result is wrong, describe the desired behavior ("stays at the top while scrolling," "overlays the image") and AI will choose correctly.

10 @media (max-width) @media print

Media Queries

@media (max-width: 575px) applies rules when the screen is 575px wide or narrower. @media (min-width: 768px) applies when 768px or wider. Bootstrap uses min-width (mobile-first); custom overrides often use max-width. The @media print block applies when the user prints — use it to strip navigation and dark backgrounds from printable pages. !important in print rules is legitimate because they must override screen styles.

In the Poster CSS
/* Phone: tighten card padding */
@media (max-width: 575px) {
    .poster-card    { padding: 1.8rem 1.4rem 1.5rem; }
    .poster-qs li   { font-size: 0.75rem; }
}

/* Print: strip dark chrome, white background */
@media print {
    #mainNav, .spark-bar, #hero, footer { display: none !important; }
    body         { background: white !important; color: black !important; }
    .poster-card { background: white !important;
                   backdrop-filter: none !important; }
}
⚡ Vibe Coder’s Note

You understand: Place @media blocks at the bottom of the CSS file so they override the rules above. Tell AI your breakpoints explicitly (e.g., "phone below 576px, tablet 576–768px") — without guidance AI may use inconsistent breakpoint values throughout a file.

AI handles: Writing the correct @media syntax. Ask specifically for @media print if you have a page that might be printed — AI won’t add it unless you ask.

Next Up: Bootstrap 5 Essentials Start Part 3 →

10 Bootstrap classes and components — the grid, the navbar, modals, and the utility system that styles the Conversation Quests series.