← Back to Blog
Tutorials·Jan 29, 2026·7 min read

4 CSS Features Every Front-End Developer Should Know in 2026

Scroll state queries, typographic whitespace trimming, sibling-index() staggering, and type-safe attr() landed in browsers in 2025. Here's how to use them in production today.

CSSWeb DevelopmentFrontendBrowser APIsStyling
JV

Jose Viscasillas

January 29, 2026 · 7 min read

4 CSS Features Every Front-End Developer Should Know in 2026

CSS evolved significantly in 2025, and most developers missed it.

Four features shipped across all major browsers that fundamentally change how we style web applications. No JavaScript. No build tools. Just CSS.

Here's what you need to know.

1. Scroll State Queries: Delete Your Intersection Observer

Remember writing JavaScript to detect scroll positions?

javascript
// The old way
const header = document.querySelector('header');

window.addEventListener('scroll', () => {
  if (window.scrollY > 100) {
    header.classList.add('scrolled');
  } else {
    header.classList.remove('scrolled');
  }
});

That's over.

The CSS Way

css
@scroll-state(scrolled-from-top > 100px) {
  header {
    background: rgba(0, 0, 0, 0.9);
    backdrop-filter: blur(10px);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  }
}

How It Works: The browser tracks scroll state natively and applies styles when conditions match.

Real-World Example: Sticky Header

css
header {
  position: sticky;
  top: 0;
  background: transparent;
  transition: all 0.3s ease;
}

@scroll-state(scrolled-from-top > 50px) {
  header {
    background: white;
    border-bottom: 1px solid #e0e0e0;
    padding-block: 0.5rem;
  }

  header .logo {
    height: 40px; /* Shrink logo when scrolled */
  }
}

Directional Scroll Detection

css
@scroll-state(scroll-direction: down) {
  header {
    transform: translateY(-100%); /* Hide header when scrolling down */
  }
}

@scroll-state(scroll-direction: up) {
  header {
    transform: translateY(0); /* Show header when scrolling up */
  }
}

Browser Support

  • Chrome 126+
  • Edge 126+
  • Safari 18.1+
  • Firefox 135+

Fallback:

css
/* Modern browsers */
@scroll-state(scrolled-from-top > 100px) {
  header { background: black; }
}

/* Fallback for older browsers */
@supports not (scroll-state: scrolled-from-top) {
  header.scrolled { background: black; }
}

And keep the JavaScript for legacy support.

2. Text-Box-Trim: Fix Typographic Whitespace

Every font has built-in whitespace above and below characters. This ruins vertical alignment.

The Problem:

html
<button>
  <svg class="icon"></svg>
  <span>Click me</span>
</button>
css
button {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

Result: Text looks misaligned because the font's built-in whitespace creates visual imbalance.

The Fix

css
button span {
  text-box-trim: both; /* Trim top and bottom whitespace */
  text-box-edge: cap alphabetic; /* Use cap height instead of line-height */
}

Before:

text
┌─────────────┐
│     ✓       │ ← Extra space
│   Button    │
│             │ ← Extra space
└─────────────┘

After:

text
┌─────────────┐
│  ✓ Button   │ ← Perfectly aligned
└─────────────┘

Real-World Use Cases

1. Card Titles

css
.card-title {
  text-box-trim: both;
  text-box-edge: cap alphabetic;
  margin-block: 0; /* No need for negative margins anymore */
}

2. Badge Components

css
.badge {
  display: inline-flex;
  align-items: center;
  padding: 0.25rem 0.75rem;
  text-box-trim: both;
  text-box-edge: cap alphabetic;
  /* Text is now optically centered */
}

3. Input Fields

css
input {
  text-box-trim: both;
  text-box-edge: cap alphabetic;
  /* Placeholder text aligns perfectly with icon */
}

Browser Support

  • Chrome 128+
  • Edge 128+
  • Safari 18.2+
  • Firefox: In development

Fallback:

css
.button span {
  text-box-trim: both;
  /* Fallback for older browsers */
  line-height: 1;
  margin-top: -0.1em;
}

3. Sibling-Index(): Staggered Animations Without JavaScript

Creating staggered animations used to require JavaScript:

javascript
// The old way
const items = document.querySelectorAll('.item');
items.forEach((item, index) => {
  item.style.animationDelay = `${index * 0.1}s`;
});

The CSS Way

css
.item {
  animation: fadeIn 0.5s ease-out;
  animation-delay: calc(sibling-index() * 0.1s);
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

Result: Items fade in one after another, automatically.

Advanced Example: Staggered Grid

css
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 1rem;
}

.grid-item {
  animation: scaleIn 0.4s ease-out backwards;
  animation-delay: calc(sibling-index() * 0.05s);
}

@keyframes scaleIn {
  from {
    opacity: 0;
    transform: scale(0.8);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

Dynamic Lists

Works with dynamic content too:

html
<ul class="list">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <!-- Items added dynamically will automatically stagger -->
</ul>
css
.list li {
  opacity: 0;
  animation: slideIn 0.5s ease-out forwards;
  animation-delay: calc(sibling-index() * 0.1s);
}

Add new <li> elements via JavaScript, and they'll automatically animate with the correct delay.

Browser Support

  • Chrome 129+
  • Edge 129+
  • Safari 18.2+
  • Firefox: Coming soon

Fallback: Use CSS variables set via JavaScript:

javascript
document.querySelectorAll('.item').forEach((item, i) => {
  item.style.setProperty('--index', i);
});
css
.item {
  animation-delay: calc(var(--index, 0) * 0.1s);
}

4. Type-Safe attr(): Use HTML Attributes in CSS (Finally)

You could always read HTML attributes in CSS:

css
.button::before {
  content: attr(data-label); /* String only */
}

But you couldn't use them for numbers or colors.

CSS attr() in 2026

css
.progress-bar {
  /* Use data-progress attribute as a number */
  width: attr(data-progress % , 0%);
  background: attr(data-color color, blue);
}
html
<div class="progress-bar" data-progress="75" data-color="#00ff00"></div>

Result: The progress bar is 75% wide with a green background.

Real-World Examples

1. Dynamic Tooltips

html
<button data-tooltip="Save changes">Save</button>
css
button::after {
  content: attr(data-tooltip);
  position: absolute;
  top: calc(100% + 0.5rem);
  left: 50%;
  transform: translateX(-50%);
  background: black;
  color: white;
  padding: 0.5rem;
  border-radius: 4px;
  opacity: 0;
  transition: opacity 0.2s;
}

button:hover::after {
  opacity: 1;
}

2. Star Ratings

html
<div class="rating" data-rating="4.5">Rating</div>
css
.rating {
  --rating: attr(data-rating number, 0);
  --fill-percent: calc(var(--rating) / 5 * 100%);

  background: linear-gradient(
    to right,
    gold var(--fill-percent),
    gray var(--fill-percent)
  );
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

.rating::before {
  content: '★★★★★';
}

3. Themeable Components

html
<div class="card"
     data-bg-color="#f0f0f0"
     data-text-color="#333"
     data-border-radius="8">
  Content
</div>
css
.card {
  background: attr(data-bg-color color, white);
  color: attr(data-text-color color, black);
  border-radius: attr(data-border-radius px, 0px);
  padding: 1rem;
}

Now you can theme components via HTML attributes without CSS variables.

Type Safety

css
.element {
  /* Type assertion with fallback */
  width: attr(data-width px, 100px);
  height: attr(data-height %, 50%);
  color: attr(data-color color, blue);
  font-size: attr(data-size em, 1em);
  opacity: attr(data-opacity number, 1);
}

If the attribute is invalid, the fallback is used.

Browser Support

  • Chrome 131+
  • Edge 131+
  • Safari 18.3+
  • Firefox: Coming Q2 2026

Fallback: Use CSS custom properties:

html
<div class="card" style="--bg: #f0f0f0; --color: #333;">
css
.card {
  background: var(--bg, white);
  color: var(--color, black);
}

Bonus: Combining Features

Here's a real-world component using all four features:

html
<nav class="nav" data-bg-color="#1a1a1a">
  <a href="#" class="nav-item">Home</a>
  <a href="#" class="nav-item">About</a>
  <a href="#" class="nav-item">Contact</a>
</nav>
css
.nav {
  position: sticky;
  top: 0;
  display: flex;
  gap: 1rem;
  padding: 1rem;
  background: transparent;
  transition: all 0.3s ease;
}

/* Scroll state query */
@scroll-state(scrolled-from-top > 100px) {
  .nav {
    background: attr(data-bg-color color, black);
    backdrop-filter: blur(10px);
  }
}

/* Sibling index stagger */
.nav-item {
  padding: 0.5rem 1rem;
  text-box-trim: both; /* Trim whitespace */
  text-box-edge: cap alphabetic;
  opacity: 0;
  animation: fadeIn 0.5s ease-out forwards;
  animation-delay: calc(sibling-index() * 0.1s);
}

@keyframes fadeIn {
  to { opacity: 1; }
}

Result:

  • Nav starts transparent
  • Becomes solid black with blur after scrolling 100px
  • Items fade in one by one on page load
  • Text is perfectly aligned

All in pure CSS.

Should You Use These Today?

Yes, with fallbacks.

Modern browsers support these features, but always provide graceful degradation:

css
/* Modern approach */
@scroll-state(scrolled-from-top > 100px) {
  header { background: black; }
}

/* Fallback */
@supports not (scroll-state: scrolled-from-top) {
  header.scrolled { background: black; }
}

Then use JavaScript to add the .scrolled class for older browsers.

Conclusion

CSS in 2026 is powerful enough to replace entire JavaScript libraries:

  • Scroll state queries → No more Intersection Observer
  • Text-box-trim → No more negative margins
  • Sibling-index() → No more stagger animation scripts
  • Type-safe attr() → No more inline styles for dynamic values

These features shipped in 2025. They're production-ready now.

Stop relying on JavaScript for styling. Modern CSS can handle it.

---

Resources:

JV

Written by Jose Viscasillas

Senior Software Engineer building video platforms at ON24. 21 years of coding experience. I write about React, TypeScript, AI, and developer tools.

Recommended Reads

📬

Subscribe to the Newsletter

New articles delivered to your inbox. No spam, unsubscribe anytime.

Join 500+ developers getting weekly insights on React, TypeScript, and building products.