CSS Evolution: Old vs. New Ways to Write Modern CSS Styles

By: Waqar Ahmed on Jul 20, 2025

CSS Evolution_ Old vs. New Ways to Write Modern CSS Styles

Introduction

CSS has evolved dramatically over the years, moving from basic styling to powerful features that once required preprocessors like Sass or LessTo understand this shift better, we’ll compare old-school CSS techniques with modern CSS approaches, covering:

  1. Variables: --var() vs. Sass $
  2. Nesting: Native CSS vs. Sass
  3. Mixins & Functions: CSS vs. Preprocessors
  4. Responsive Design: Media Queries vs. Container Queries
  5. Selectors: :has() vs. JavaScript Workarounds

By the end, you’ll know how to write cleaner, more efficient CSS—without relying on extra tools.

1. Variables: CSS Custom Properties vs. Sass

Old Way: Sass Variables

$primary-color: #3498db;  
$font-stack: 'Arial', sans-serif;

body {
color: $primary-color;
font-family: $font-stack;
}

✅ Pros:

  • First, it’s dynamic (updatable with JavaScript).
  • Secondly, no preprocessor needed (native browser support).

❌ Cons:

  • Requires a build step (Sass compiler).
  • Static (can’t change at runtime).

New Way: CSS Custom Properties

:root {
--primary-color: #3498db;
--font-stack: 'Arial', sans-serif;
}

body {
color: var(--primary-color);
font-family: var(--font-stack);
}

✅ Pros:

  • Dynamic (updatable with JavaScript).
  • No preprocessor needed (native browser support).

❌ Cons:

  • Limited math support (requires calc()).

When to Use Which?

  • Use Sass if supporting legacy browsers.
  • On the other hand, use CSS variables for modern theming and runtime changes.

2. Nesting: Native CSS vs. Sass

Old Way: Sass Nesting

.card {  
padding: 1rem;
.title {
font-size: 1.5rem;
&:hover { color: red; }
}
}

New Way: Native CSS Nesting (2023+)

.card {  
padding: 1rem;
& .title {
font-size: 1.5rem;
&:hover { color: red; }
}
}

✅ Now Supported in Modern Browsers.

Key Differences:

FeatureSass NestingNative CSS Nesting
SyntaxNo & requiredIn contrast, requires &
Browser SupportWorks everywhere (compiled)Meanwhile, modern browsers only

3. Mixins & Functions: CSS vs. Sass

Old Way: Sass Mixins

@mixin flex-center { 
display: flex;
justify-content: center;
align-items: center;
}

.container { @include flex-center; }

New Way: CSS @mixin (Proposal) & color-mix()

While CSS doesn’t have exact mixins yet, new functions like color-mix() replace some Sass features:

.button {  
background: color-mix(in srgb, red 30%, blue 70%);
}

Alternative: CSS @apply (Deprecated)
⚠️ Avoid @apply—it was removed from specs.

Best Modern Alternative:

  • Use CSS variables + calc() for reusable logic.
  • For color mixing, color-mix() is a game-changer.

4. Responsive Design: Media Queries vs. Container Queries

Old Way: Media Queries

@media (max-width: 768px) {  
.sidebar { display: none; }
}

New Way: Container Queries (2023+)

.component {  
container-type: inline-size;
}

@container (max-width: 500px) {
.card { flex-direction: column; }
}

✅ Why Better?

  • Unlike media queries, they respond to parent containers.
  • As a result, they’re ideal for reusable components.

Browser Support: Chrome 105+, Safari 16+, Firefox 110+.

5. Parent Selector: :has() vs. JavaScript

Old Way: JavaScript Workarounds

document.querySelectorAll('.parent').forEach(el => {  
if (el.querySelector('.child')) {
el.classList.add('has-child');
}
});

New Way: CSS :has() (2022+)

.parent:has(.child) {  
border: 2px solid blue;
}

✅ Finally, a pure CSS solution!

Conclusion: Should You Still Use Sass?

FeatureOld (Sass)New (Native CSS)
Variables$var--var() (dynamic)
NestingYesYes (with &)
Mixins@mixinLimited (use variables)
Responsive LogicMedia QueriesContainer Queries
Parent SelectorNot possible:has()

Final Recommendation:

  • For new projects, embrace modern CSS.
  • For legacy systems, keep Sass until refactoring.

Next Steps

  1. Test browser support on caniuse.com.
  2. Experiment with color-mix()@scope, and :has().
  3. Refactor old CSS incrementally.