These 21 New CSS Features That Deserve More Attention
The last couple of years have been incredible for CSS. There have been so many new features that have come out, and they’re absolute game changers for how I write CSS. In this article, I’m going to share my 21 favorite CSS features in rapid-fire style so you can get as much information as quickly as possible. 1. CSS Layers One of my favorite properties is layer. It’s been out for quite a while, but not many people seem to use or talk about it. Essentially, a CSS layer allows you to create different layers—for example, reset, theme, defaults, layouts, components, and utils. Since the utils layer comes after components, everything in utils is more specific than components, regardless of selector specificity. Check out this quick example: @layer reset, theme, defaults, layouts, components, utils; @layer utils { * { color: red; } } You can even import CSS into a specific layer: @import url("theme.css") layer(theme); 2. Text Wrap: Balance Next up is text-wrap. I’m using text-wrap: balance on an item, and you can see that as the page size changes, the text splits onto two or three lines—but it’s always balanced equally. Remove text-wrap: balance and you’ll notice the text isn’t balanced anymore, with a single word ending up on its own line. This feature is super useful for headers and other text elements. h1 { text-wrap: balance; } 3. Nesting Another feature you might have noticed in my code is nesting. I use nesting a lot—for media queries, state-based classes, or even grouping selectors together. For example, I can nest media queries right inside my main header title: .main-header { font-size: 2rem; @media (max-width: 600px) { font-size: 1.5rem; } &.red { color: red; } .green { color: green; } } This makes the code so much more organized and readable. 4. Container Queries Let’s talk about container queries. You’ve probably used media queries before, but container queries let you style an element based on the size of its container—not the viewport. For instance, I have house cards that change layout depending on the container size: .house-card { container-type: inline-size; } @container (min-width: 450px) { .house-card { flex-direction: row; } } @container (max-width: 449px) { .house-card { flex-direction: column; } } This means my components adjust responsively, regardless of the page size—a really powerful feature, especially in component-based frameworks like React. 5. Relative Colors Relative colors are one of my absolute favorites. They let you take one color and, using functions and formulas, convert it into another color—even in an entirely different color space. For example, I define a background color with OK LCH values and then derive my button border by subtracting 15% from the lightness value: :root { --bg-color: oklch(75% 0.05 30); } .button { background-color: var(--bg-color); border: 2px solid color-mod(var(--bg-color) l(-15%)); } .button:hover { background-color: color-mod(var(--bg-color) l(-7.5%)); box-shadow: 0 0 10px color-mod(var(--bg-color) l(-15%)); } This makes creating themes and hover effects incredibly flexible. 6. Parent Selector (:has()) Perhaps one of the coolest features is the parent selector—the :has() pseudo-class. It lets me change the style of a parent element based on what’s happening inside a child. For example, I can change an input group’s color if its input is valid or invalid—all without a single line of JavaScript: .input-group:has(input:valid) { border-color: green; } .input-group:has(input:invalid) { border-color: red; } It’s an absolute game changer for dynamic styling purely in CSS. 7. Defining Custom Properties with @property I also love defining custom properties using the @property keyword. It works like a normal custom property, but with extra features—you can specify a type (syntax), control inheritance, and even set an initial value. This means your custom properties become animatable! @property --main-color { syntax: ''; inherits: false; initial-value: red; } :root { --main-color: green; } body { color: var(--main-color); } Whenever I need type safety and animatability, I jump straight to @property. 8. Subgrid Subgrid is a feature that took a while to hit browsers, but it’s here now. It allows a child element to share the grid layout of its parent, so nested grids align perfectly: .parent-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 2rem; } .child-grid { display: grid; grid-template-columns: subgrid; } This is especially useful when you have complex, nested grid layouts. 9. Multi-Value Display This feature isn’t entirely new, but it changes the way we define display properties by separating the outer display (how an element lays itself out) from the inner display (

The last couple of years have been incredible for CSS. There have been so many new features that have come out, and they’re absolute game changers for how I write CSS. In this article, I’m going to share my 21 favorite CSS features in rapid-fire style so you can get as much information as quickly as possible.
1. CSS Layers
One of my favorite properties is layer. It’s been out for quite a while, but not many people seem to use or talk about it. Essentially, a CSS layer allows you to create different layers—for example, reset
, theme
, defaults
, layouts
, components
, and utils
. Since the utils
layer comes after components
, everything in utils
is more specific than components
, regardless of selector specificity. Check out this quick example:
@layer reset, theme, defaults, layouts, components, utils;
@layer utils {
* {
color: red;
}
}
You can even import CSS into a specific layer:
@import url("theme.css") layer(theme);
2. Text Wrap: Balance
Next up is text-wrap. I’m using text-wrap: balance
on an item, and you can see that as the page size changes, the text splits onto two or three lines—but it’s always balanced equally. Remove text-wrap: balance
and you’ll notice the text isn’t balanced anymore, with a single word ending up on its own line. This feature is super useful for headers and other text elements.
h1 {
text-wrap: balance;
}
3. Nesting
Another feature you might have noticed in my code is nesting. I use nesting a lot—for media queries, state-based classes, or even grouping selectors together. For example, I can nest media queries right inside my main header title:
.main-header {
font-size: 2rem;
@media (max-width: 600px) {
font-size: 1.5rem;
}
&.red {
color: red;
}
.green {
color: green;
}
}
This makes the code so much more organized and readable.
4. Container Queries
Let’s talk about container queries. You’ve probably used media queries before, but container queries let you style an element based on the size of its container—not the viewport. For instance, I have house cards that change layout depending on the container size:
.house-card {
container-type: inline-size;
}
@container (min-width: 450px) {
.house-card {
flex-direction: row;
}
}
@container (max-width: 449px) {
.house-card {
flex-direction: column;
}
}
This means my components adjust responsively, regardless of the page size—a really powerful feature, especially in component-based frameworks like React.
5. Relative Colors
Relative colors are one of my absolute favorites. They let you take one color and, using functions and formulas, convert it into another color—even in an entirely different color space. For example, I define a background color with OK LCH values and then derive my button border by subtracting 15% from the lightness value:
:root {
--bg-color: oklch(75% 0.05 30);
}
.button {
background-color: var(--bg-color);
border: 2px solid color-mod(var(--bg-color) l(-15%));
}
.button:hover {
background-color: color-mod(var(--bg-color) l(-7.5%));
box-shadow: 0 0 10px color-mod(var(--bg-color) l(-15%));
}
This makes creating themes and hover effects incredibly flexible.
6. Parent Selector (:has()
)
Perhaps one of the coolest features is the parent selector—the :has()
pseudo-class. It lets me change the style of a parent element based on what’s happening inside a child. For example, I can change an input group’s color if its input is valid or invalid—all without a single line of JavaScript:
.input-group:has(input:valid) {
border-color: green;
}
.input-group:has(input:invalid) {
border-color: red;
}
It’s an absolute game changer for dynamic styling purely in CSS.
7. Defining Custom Properties with @property
I also love defining custom properties using the @property
keyword. It works like a normal custom property, but with extra features—you can specify a type (syntax), control inheritance, and even set an initial value. This means your custom properties become animatable!
@property --main-color {
syntax: '' ;
inherits: false;
initial-value: red;
}
:root {
--main-color: green;
}
body {
color: var(--main-color);
}
Whenever I need type safety and animatability, I jump straight to @property
.
8. Subgrid
Subgrid is a feature that took a while to hit browsers, but it’s here now. It allows a child element to share the grid layout of its parent, so nested grids align perfectly:
.parent-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
}
.child-grid {
display: grid;
grid-template-columns: subgrid;
}
This is especially useful when you have complex, nested grid layouts.
9. Multi-Value Display
This feature isn’t entirely new, but it changes the way we define display properties by separating the outer display (how an element lays itself out) from the inner display (how its children are laid out). Instead of relying on inline-flex or inline-grid, you now have two distinct properties:
.element {
display: inline flex;
}
This added flexibility is a welcome change in layout handling.
10. display: contents
The display: contents
property is a lifesaver when you need a wrapper element for styling purposes without disrupting your layout—especially in flexbox or grid. It essentially makes the wrapper “disappear” from the layout flow, letting the child elements behave as if they were directly inside the container:
.wrapper {
display: contents;
}
11. Logical Properties
Logical properties let you define layout attributes (like left, right, top, bottom, width, and height) using logical rather than physical properties. For example, instead of padding-left
, you can use padding-inline-start
. This is crucial for sites supporting multiple languages and writing directions:
.element {
padding-inline-start: 1rem;
}
It automatically adjusts based on the writing mode and text direction.
12. Backdrop Styling
Next, let’s discuss the backdrop property. This feature allows you to style the backdrop of elements like the element. Check out how I style the backdrop for a modal dialog:
dialog::backdrop {
background: rgba(0, 0, 0, 0.5);
transition: opacity 0.3s ease;
}
When I open the dialog, the backdrop animates in nicely.
13. Transition Behavior with allow-discreet
and Starting Styles
Some CSS properties—like display—have binary values and can’t usually be animated. With transition-behavior: allow-discreet
and starting styles, I can animate between these states. For instance, here’s how I animate a modal:
.modal {
display: block;
opacity: 0;
transition: opacity 0.5s ease;
transition-behavior: allow-discreet;
starting-style: { opacity: 0; transform: scale(0.95); }
}
.modal.open {
opacity: 1;
transform: scale(1);
}
Note: Browser support for these specific features may vary.
14. Field-Sizing Content
Field-sizing content is another feature I really enjoy. It allows text areas to automatically grow based on the content inside—without any JavaScript. For example:
textarea {
field-sizing: content;
resize: none;
}
As you type, the text area grows vertically (or horizontally, if you choose), though support is currently limited mainly to Chromium-based browsers.
15. The @scope
Property
The @scope
property lets you limit the application of CSS styles to a specific container. This is especially useful for component libraries where you want your styles isolated. For instance:
@scope (section.featured) {
h2 {
color: blue;
}
p {
font-size: 1.2rem;
}
}
Anything outside of section.featured
won’t be affected.
16. Anchor Property
One of the most hyped features is the anchor property. It allows you to anchor an element to another element’s position using named anchors. For example, I define an anchor and then position an info box relative to it:
/* Define the anchor on an element */
.anchor {
position: anchor(myAnchor);
}
/* Use the anchor to position another element */
.info-box {
position: absolute;
top: anchor(myAnchor, bottom);
left: anchor(myAnchor, right);
}
In another example, as I move the anchors, the position of the elements inside a box changes automatically based on the defined anchor positions. The magic here is that CSS handles all the positioning without any JavaScript.
17. Container Style Queries
This one is a bit experimental. Container style queries allow you to style elements based on the styles or custom properties within their container. For example, you can create a container that applies specific styles if a custom property (like an accent color) is set:
.container {
container-type: style;
--accent-color: blue;
}
@container (style(--accent-color: blue)) {
.child {
border: 2px solid blue;
}
}
While I don’t see this being used widely just yet, it’s an interesting addition for very specific use cases.
18. Interpolate Size with allow-keywords
Animating properties like height from max-content
to a fixed value has always been a challenge. With interpolate-size: allow-keywords
, you can animate between keywords such as auto
, min-content
, and max-content
using calc()
. Check out this example:
.element {
height: max-content;
transition: height 0.5s ease;
interpolate-size: allow-keywords;
}
.element:hover {
height: 2.5rem;
}
Without this, the height would jump instantly between states rather than smoothly transitioning.
19. CSS Aspect Ratio
A newer addition to modern CSS is the aspect-ratio property, which makes it incredibly easy to maintain the proportions of an element. No more messy padding hacks—just set the aspect ratio and let the browser handle the rest.
.aspect-box {
width: 100%;
aspect-ratio: 16 / 9;
background: lightgray;
}
This property is perfect for responsive videos, images, or any content that needs to maintain a specific ratio.
20. CSS Scroll Snap
Last but not least, CSS Scroll Snap is an awesome feature that lets you create smooth, controlled scrolling experiences. It helps you lock the scroll position to specific points—ideal for carousels or full-page scrolling layouts.
.scroll-container {
scroll-snap-type: x mandatory;
overflow-x: scroll;
display: flex;
}
.scroll-item {
scroll-snap-align: center;
min-width: 300px;
margin-right: 1rem;
background: #eee;
padding: 1rem;
}
With CSS Scroll Snap, your users will enjoy a seamless and polished scrolling experience.
21. View Transitions API
Now, the next feature I want to talk about is the View Transitions API. This is one of the coolest, most hyped new CSS features that’s coming our way. It allows you to smoothly animate transitions between different view states on your page without needing a ton of extra JavaScript. Imagine having a page transition that just flows naturally, making your UI feel incredibly dynamic and polished—all handled right in CSS with minimal code.
/* Simple CSS to designate an element for view transitions */
.card {
view-transition-name: cardFade;
transition: opacity 0.5s ease;
}
This API is a real game changer for creating seamless transitions between different states of your app or website. I’m really excited to see how it evolves and how soon we can all start using it in production.
Final Thoughts
That’s all 20 of my favorite new CSS features. They’re revolutionizing the way we write CSS, making our code more responsive, dynamic, and ultimately more enjoyable to work with. Whether you’re just starting out or you’re an advanced developer looking to take your skills to the next level, these features can help you build your dream project sooner.
Thank you very much for reading—and happy coding!
Stay connected with me on my other platforms: