Simple CSS. Again

satya - 8/17/2025, 2:23:54 PM

To understand CSS in the context of next.js

To understand CSS in the context of next.js

satya - 8/17/2025, 2:45:53 PM

Project structure


my-app/
  app/
    globals.css
    layout.tsx
    page.tsx
  components/
    Button.tsx
    Button.module.css
    LinkText.tsx
    LinkText.module.css
    Field.tsx
    Field.module.css
    SimpleList.tsx
    SimpleList.module.css

satya - 8/17/2025, 2:48:45 PM

A typical global.css


/* 1) CSS Reset-ish (small, modern) */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html:focus-within { scroll-behavior: smooth; }

body { min-height: 100vh; text-rendering: optimizeLegibility; 
-webkit-font-smoothing: antialiased; }

img, picture, video, canvas, svg { display: block; max-width: 100%; }
input, button, textarea, select { font: inherit; }

/* 2) Theme tokens (colors, spacing, radius, shadows) */
:root {
  /* colors */
  --color-bg: #0b1220;          /* page background */
  --color-surface: #121a2b;     /* cards, sections */
  --color-border: #2b3752;      /* subtle borders */
  --color-text: #e5eaf3;        /* primary text */
  --color-muted: #a7b1c5;       /* secondary text */
  --color-link: #6ea8fe;        /* links */
  --color-primary: #5b8cff;     /* brand */
  --color-primary-700: #3f6ff0; /* brand darker */
  --color-danger: #ff6b6b;
  --color-success: #5bd6a1;

  /* spacing & radius */
  --space-1: 0.25rem; /* 4px  */
  --space-2: 0.5rem;  /* 8px  */
  --space-3: 0.75rem; /* 12px */
  --space-4: 1rem;    /* 16px */
  --space-6: 1.5rem;  /* 24px */
  --radius-sm: 6px;
  --radius-md: 10px;
  --shadow-1: 0 1px 2px rgba(0,0,0,.12), 0 3px 8px rgba(0,0,0,.14);
}

/* 3) Base typography and layout */
html, body { color: var(--color-text); background: var(--color-bg); }

body { font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, 
  Roboto, "Helvetica Neue", Arial, "Noto Sans", "Apple Color Emoji", 
  "Segoe UI Emoji"; line-height: 1.6; }
main { max-width: 900px; margin: 0 auto; padding: var(--space-6); }

h1 { font-size: clamp(1.6rem, 3vw, 2.2rem); margin-bottom: var(--space-4); }
h2 { font-size: clamp(1.3rem, 2.5vw, 1.6rem); margin-top: var(--space-6); margin-bottom: var(--space-2); }
p + p { margin-top: var(--space-2); }

/* 4) Links */
a { color: var(--color-link); text-decoration: none; }
a:hover { text-decoration: underline; }

/* 5) Focus styles (keyboard a11y) */
:where(a, button, input, select, textarea, summary):focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* 6) Containers */
.section { background: var(--color-surface); 
  border: 1px solid var(--color-border); 
  border-radius: var(--radius-md); 
  box-shadow: var(--shadow-1); padding: var(--space-6); }

.muted { color: var(--color-muted); }

/* 7) Small utilities */
.stack > * + * { margin-top: var(--space-2); }   /* vertical rhythm */
.row { display: flex; gap: var(--space-2); align-items: center; }

satya - 8/17/2025, 3:06:43 PM

Psuedo elements: Some examples

  1. ::before ? insert (before content)
  2. ::after ? insert (after content)
  3. ::first-line ? typography (first line)
  4. ::first-letter ? dropcap (first letter)
  5. ::marker ? list (bullet/number)
  6. ::selection ? highlight (user selection)

satya - 8/17/2025, 3:07:42 PM

Psuedo classes: Some examples

  1. :hover ? hover effect
  2. :active ? clicked state
  3. :focus ? focused by keyboard/tab
  4. :visited ? visited link
  5. :first-child ? first element in a parent

satya - 8/17/2025, 3:14:13 PM

Standalone psuedo classes

  1. :root ? the root element (in HTML, <html>)
  2. :any-link ? any link (:link or :visited)
  3. :link ? unvisited links
  4. :visited ? visited links
  5. :fullscreen ? the element in fullscreen mode
  6. :scope ? the scoping element (defaults to :root)
  7. :target ? element pointed to by the URL fragment
  8. :defined ? custom elements that have been defined

satya - 8/17/2025, 3:15:13 PM

what are they about?

  1. They describe a global state or a unique property of an element, not relative to another selector
  2. describes a special structural role or global condition

satya - 8/17/2025, 3:15:39 PM

Attached pseudo-classes (always come after a selector)

  1. :hover ? when mouse is over the element
  2. :focus ? when element has keyboard/mouse focus
  3. :active ? while the element is being clicked
  4. :first-child / :last-child ? first/last child of parent
  5. :nth-child(n) / :nth-of-type(n) ? element in a certain position
  6. :only-child / :only-of-type ? element that?s the only one
  7. :checked ? checkboxes/radios when checked
  8. :disabled / :enabled ? form controls
  9. :empty ? element with no children

satya - 8/17/2025, 3:16:42 PM

what are they about?

  1. They describe a state or position relative to a specific element
  2. state of an element relative to siblings or interaction

satya - 8/17/2025, 3:28:23 PM

The focus psudeo classes

  1. :focus ? Matches the element that itself has focus (e.g., an input, button, or link the user clicked or tabbed into).
  2. :focus-within ? Matches an element if it OR any of its descendants has focus. Useful for styling parent containers when a child is active.
  3. :focus = ?this element has focus.?
  4. :focus-within = ?this element or something inside it has focus.?

satya - 8/17/2025, 3:35:08 PM

The Selectors...

  1. Universal (*): Selects all elements.
  2. Descendant (A B): B inside A (any depth).
  3. Child (A > B): B is a direct child of A.
  4. Adjacent sibling (A + B): B immediately follows A.
  5. General sibling (A ~ B): B is any sibling after A.
  6. Selector list (A, B): A or B (applies to both).
  7. Functional pseudo-class :is(A, B, C): Matches any of the selectors inside (shorter code).
  8. Functional pseudo-class :where(A, B, C): Like :is(), but adds zero specificity.
  9. Attribute [attr]: Elements with the attribute.
  10. Attribute [attr="value"]: Attribute equals value.
  11. Attribute [attr~="value"]: Attribute contains value in a space-separated list.
  12. Attribute [attr|="value"]: Attribute starts with value (or value-? with hyphen).
  13. Attribute [attr^="value"]: Attribute starts with value (prefix match).
  14. Attribute [attr$="value"]: Attribute ends with value (suffix match).
  15. Attribute [attr*="value"]: Attribute contains value (substring match).

satya - 8/17/2025, 5:07:15 PM

The where...


:where(a, button, input, select, textarea, summary):focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

is equivalent to

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

satya - 8/17/2025, 5:18:23 PM

One rule, Coming later in the source over-rides the previous

One rule, Coming later in the source over-rides the previous

satya - 8/17/2025, 5:28:45 PM

Same element and it various states like hover...

  1. Specificity:
  2. button:hover ? (0,0,1,1)
  3. button ? (0,0,0,1)
  4. with where....
  5. :where(button):hover ? (0,0,1,0)
  6. button ? (0,0,0,1)
  7. with classes...
  8. :where(button):hover { background: black; }
  9. /* (0,0,1,0) ? base hover */
  10. .btn { background: gray; }
  11. /* (0,0,1,0) ? same specificity, later wins */

satya - 8/17/2025, 5:29:56 PM

Cheatsheet to understand where and specificity

  1. Plain element later vs :where(button):hover ? hover still wins
  2. Class later vs :where(button):hover ? class can win on tie (later source order)
  3. Plain element later vs button:hover ? hover wins (more specific)
  4. Class later vs button:hover ? hover still wins (more specific)

satya - 8/17/2025, 5:34:36 PM

Class alone vs neutralized


.btn { ? }              /* specificity: (0,0,1,0) */
:where(.btn) { ? }      /* specificity: (0,0,0,0) */

satya - 8/17/2025, 5:35:23 PM

Inutively....

  1. classes (and IDs) increase specificity normally.
  2. Inside :where(...), they don?t. Only the parts outside :where contribute.

satya - 8/17/2025, 5:39:49 PM

Understand this example better....


/* Base focus ring: virtual/soft */
:where(a, button):focus-visible { outline: 2px solid var(--ring); }

/* Component override: easy to take over */
.btn { outline: none; }  /* same specificity, later wins */

satya - 8/17/2025, 5:40:56 PM

Analogy: the where

  1. May be there is another analogy (may not be exact) ...
  2. In OO programming by indicating that something is a virtual method....
  3. you are saying...safe enough to override.... as opposed to another method that you can override but stayed unmentioned....the where being the former, giving the allowance

satya - 8/17/2025, 5:48:51 PM

In the example above....

  1. The weakness of where...though intentional allowed a component to take over the whole button...
  2. If it chooses....to

satya - 8/17/2025, 5:50:39 PM

So how do I summarize?

  1. go with the OO analogy
  2. follows the "is" in terms of ease (not specificity)
  3. allows to set baselines or resets (as they are called)
  4. Simpler syntax as opposed to comma separated classes or elements

satya - 8/17/2025, 5:53:37 PM

Here is a list of selectors


/* Elements */
html                 /* root element */
body                 /* document body */
main                 /* main content */
header               /* page/section header */
footer               /* page/section footer */
h1                   /* heading level 1 */
p                    /* paragraph */
a                    /* link */
img                  /* image */
button               /* button */
input                /* form input */
select               /* select box */
textarea             /* multi-line input */
ul                   /* unordered list */
li                   /* list item */

/* Classes & IDs */
.card                /* class */
.card.primary        /* class with modifier */
#app                 /* id */

/* Attribute selectors */
input[type="text"]           /* exact match */
a[target="_blank"]           /* opens new tab */
a[href^="https://"]          /* starts with */
a[href$=".pdf"]              /* ends with */
a[href*="docs"]              /* contains */
input[aria-invalid="true" i] /* case-insensitive match */

/* Pseudo-classes (state & UI) */
a:hover              /* mouse over */
button:active        /* active press */
input:focus          /* focused */
:focus-visible       /* keyboard-visible focus */
:focus-within        /* element containing a focused descendant */
:disabled            /* disabled controls */
:enabled             /* enabled controls */
:checked             /* checked checkbox/radio */
:indeterminate       /* tri-state checkbox */
:required            /* required input */
:optional            /* optional input */
:read-only           /* readonly input */
:placeholder-shown   /* input shows placeholder */
:valid               /* passes validation */
:invalid             /* fails validation */
:target              /* URL fragment target */

/* Structural pseudo-classes */
:first-child         /* first child of parent */
:last-child          /* last child of parent */
:only-child          /* only child of parent */
:nth-child(2)        /* 2nd child */
:nth-child(odd)      /* odd children */
:nth-child(3n+1)     /* every 3rd, starting at 1 */
:nth-of-type(2)      /* 2nd element of same type */
:is(h1, h2, h3)      /* match any of these, normal specificity */
:where(h1, h2, h3)   /* match any of these, zero specificity */
:not(.active)        /* not matching .active */
:has(> img)          /* element that has a direct child img */

/* Pseudo-elements */
::before             /* generated content before */
::after              /* generated content after */
::placeholder        /* placeholder text styling */
::selection          /* selected text (non-inherited) */
::marker             /* list item marker/bullet */
::file-selector-button /* file input button */
::backdrop           /* backdrop of a modal dialog */

/* Document/root */
:root                /* top-level element (html) */
:scope               /* current query scope */

/* Combinators */
article p            /* descendant (p anywhere inside article) */
article > p          /* direct child */
h2 + p               /* adjacent sibling (p immediately after h2) */
h2 ~ p               /* general siblings (any p after h2) */

/* Grouping */
h1, h2, h3           /* group multiple selectors */

/* Common patterns (handy) */
nav :is(a, button):focus-visible   /* shared focus ring targets */
:where(article, aside) :where(h1, h2, h3)  /* low-specificity typography base */
.card :not(:last-child)            /* all children except last */
main :has(> .error)                /* main that contains a direct .error child */

satya - 8/18/2025, 5:52:42 PM

Order of understanding

  1. Understand selectors
  2. That includes elements, classes, pseudo classes and pseudo elements
  3. ------------ the root
  4. Understand :root
  5. Understand custom properties, var()
  6. Understand :is, :where
  7. --------- others
  8. Resets
  9. Tokens
  10. Containers like sections, stacks, rows
  11. -------------------Now
  12. Take a look at a large functional global.css
  13. Read the global.css with that knowledge