Modern CSS Techniques - Practical Examples

This document shows incremental improvements you can make to your existing CSS, building on what you already have.

1. Fluid Typography with clamp()

Instead of:

--text-font-size: 20px;
--text-font-size-mobile: 22px;

Use:

--text-font-size: clamp(18px, 4vw, 22px);
/* Minimum: 18px, Preferred: 4vw (scales with viewport), Maximum: 22px */

Real example from your code:

/* Old approach - requires media queries */
font-size: var(--text-font-size); /* 20px */
@media (max-width: 576px) {
  font-size: var(--text-font-size-mobile); /* 22px */
}

/* New approach - fluid, no media query needed */
font-size: clamp(18px, 4vw + 0.5rem, 22px);

Why: Text scales smoothly between breakpoints instead of jumping at media query boundaries.


2. Logical Properties (You’re already using some!)

Instead of:

padding: 50px 15px 35px;
margin-left: 20px;
margin-right: 20px;

Use:

padding-block: 50px 35px;  /* top and bottom */
padding-inline: 15px;      /* left and right */
margin-inline: 20px;       /* left and right */

Why: Works automatically for RTL languages and is more semantic (block = vertical, inline = horizontal).


3. color-mix() for Dynamic Color Variations

Instead of:

--accent-color: #f15403;
--accent-color-lighter: #ff803f;  /* manually calculated */

Use:

--accent-color: #f15403;
--accent-color-lighter: color-mix(in srgb, var(--accent-color) 70%, white);
/* Mixes 70% accent color with 30% white */

Why: Automatically generates lighter/darker variants. Change the base color, variants update automatically.


4. :is() and :where() for Cleaner Selectors

Instead of:

article a, 
article a:visited,
.related-links a {
  color: var(--orange-text-lighter);
}

Use:

:is(article a, .related-links a):is(:link, :visited) {
  color: var(--orange-text-lighter);
}

Or even simpler with :where() (lower specificity):

:where(article, .related-links) a:where(:link, :visited) {
  color: var(--orange-text-lighter);
}

Why: Reduces repetition and makes selectors more readable.


5. @layer for Cascade Management

Instead of fighting specificity with !important:

@layer base, components, utilities;

@layer base {
  a {
    color: blue;
  }
}

@layer components {
  .photo-card a {
    color: orange; /* Always wins over base, no !important needed */
  }
}

Why: Explicit control over cascade order without specificity wars.


6. Container Queries (When Component Size Matters More Than Viewport)

Instead of:

@media (min-width: 769px) {
  .photo-info {
    display: none;
  }
}

Use (when the component’s container size matters):

.photo-card {
  container-type: inline-size;
}

@container (min-width: 300px) {
  .photo-info {
    display: block;
  }
}

Why: Responsive to the component’s container, not just the viewport. Great for reusable components.


Quick Wins You Can Try Today

  1. Convert one font size to clamp() - Pick --text-font-size-large and make it fluid
  2. Replace one padding: X Y with padding-block/inline - Start with header padding
  3. Use color-mix() for one color variant - Try --accent-color-lighter
  4. Use :is() in one complex selector - Simplify a multi-selector rule

Start with one, see how it feels, then gradually apply the pattern elsewhere.