Styling based on container element
.container {
container-type: inline-size;
}
@container (width => 600px) {
.card {
display: flex;
}
}
Container queries also bring new units:
cqw, cqh, cqi, cqb, cqmin, cqmax
@container (width => 600px) {
.card {
display: flex;
font-size: 2cqi;
}
}
@container style()Styling based on container element's style
@container style(--theme: dark) {
.card {
background-color: #202020;
color: #f0f0f0;
}
}
:has()Parent selector and much more
ul + .message {
display: none;
}
/* If the list has no items, display the message */
ul:not(:has(> li)) + .message {
display: block;
}
Generate different layers of specificity
@layer reset, defaults, components, utilities, overrides;
@import url('framework.css') layer(components.framework);
@layer utilities {
[data-color='brand'] { color: var(--brand, rebeccapurple); }
}
@layer defaults {
a:any-link { color: maroon; }
}
a { color: mediumvioletred; }
Style and at-rules can be nested like in preprocessors
.card {
background-color: #fff;
&:hover {
background-color: #eee;
}
@media (width >= 600px) {
border: 1px solid #aaa;
}
}
Nested grids controlled by a parent grid
.outer-grid {
display: grid;
grid-template-rows: repeat(4, minmax(100px, auto));
background-color: #333;
}
.inner-grid {
display: grid;
grid-row: 2 / 4;
grid-template-rows: subgrid;
background-color: #666;
}
@supports selector()Checks support for specific selectors
@supports selector(:nth-child(1 of .foo)) {
:nth-child(1 of .foo) { font-size: 1.2rem; }
}
@supports selector(:has(+ a)) {
:has(+ a) { color: green; }
}
@supports font-format() + @supports font-tech()Checks support for specific font formats or technologies
@supports (font-format(woff2)) {
.font-format-supported { display: block; }
}
@supports (font-tech(palettes)) {
.font-tech-supported { display: block; }
}
aspect-ratioDefines a preferred aspect ratio
.image {
width: 100%;
aspect-ratio: 16 / 9;
}
conic-gradient() + repeating-conic-gradient()Circular color transitions around a center point
.checkerboard {
background-image: repeating-conic-gradient(#000 0% 25%, #fff 0% 50%);
background-size: 60px 60px;
}
:is() + :where()Simplifies selecting multiple elements
article > :is(h1, h2, h3, h4, h5, h6) {
font-family: "soleil", Helvetica, Arial, sans-serif;
}
:not():not() now supports complex selectors
/* All <p>s outside an <article> */
p:not(article *) {
background-color: rgb(0 0 0 / 0.2);
}
scale, rotate and translateSeparate transformation properties
.img:hover {
scale: 1.2;
}
a.open .arrow {
rotate: 90deg;
}
.img {
translate: 40px;
}
@propertyDefines custom properties that can be used like built-in properties
@property --my-color {
syntax: "<color>";
inherits: false;
initial-value: #c0ffee;
}
a { color: var(--my-color); }
Mathematical expressions in media queries
@media (600px <= width) { … }
@media (width < 80em) { … }
@media (400px < width <= 1000px) { … }
Viewport units based on large, small and dynamic viewport lengths
.box {
width: 80lvw;
height: 50dvh;
padding: 1svh 1svw;
}
Color functions supporting different color spaces
lch(), lab(), oklch(), oklch() and color()
.box {
background-color: hwb(0 100% 0% / 50%);
color: #0008;
border-color: #FFFFFFA0;
text-decoration-color: color(display-p3 -0.6112 1.0079 -0.2192);
background-color: lch(29.2345% 44.2 27);
color: lab(62.2345% -34.9638 47.7721);
border-color: oklab(40.101% 0.1147 0.0453);
text-decoration-color: oklch(0.66016 0.15546 134.231);
}
color-mix()Mixes two colors using a color space to create a new color
.box {
background-color: color-mix(in srgb, #34c9eb 10%, white);
}
Allows defining new colors based on another color
.relative-colors {
--accent: darkblue;
color: rgb(from var(--accent) r g b / 0.5 );
background-color: lch(from var(--accent) l c calc(h + 180));
}
Media features to check different device aspects and user preferences
@media (prefers-color-scheme: dark) { … }
@media (prefers-contrast: more) { … }
@media (prefers-reduced-motion) { … }
@media (prefers-reduced-data: reduce) { … }
@media (dynamic-range: high) { … }
@media (update: slow) { … }
@media (forced-colors: active) { … }
:modalSelector to target elements displayed modally
:modal {
border: 5px solid red;
background-color: yellow;
box-shadow: 3px 3px 10px rgb(0 0 0 / 0.5);
}
:focus-visible + :focus-withinSelect elements when the focus ring is visible or when the focus is placed somewhere inside an element
input:focus-visible {
box-shadow: 0 0 4px skyblue;
}
fieldset:focus-within {
background-color: rgb(0 0 0 / 0.1);
}
:user-valid + :user-invalidSelects (in-)valid form elements when the user interacted with them
input:user-invalid {
background-color: rgb(255 0 0 / 0.6);
}
:placeholder-shownSelects inputs where the placeholder is showns
input:placeholder-shown {
background-color: #f0f0f0;
color: #080808;
}
:autofillSelects form fields that are filled by selecting a predefined option
input:autofill {
background-color: rgb(0 0 0 / 0.2);
}
::file-selector-buttonTargets the button within <input type="file"> elements
::file-selector-button {
appearance: none;
background-color: navy;
color: white;
}
backdrop-filterFilters the backdrop of an element
dialog {
background-color: rgb(255 255 255 / 0.5);
backdrop-filter: blur(10px);
}
linear().box {
animation-timing-function: linear(0, 0.25 75%, 1);
}
overflow: clip.box {
overflow: clip;
}
appearanceinput, button, select, textarea {
appearance: none;
border: 2px solid gray;
}
text-decoration-thickness + text-underline-offseta {
text-decoration-thickness: 0.1em;
text-underline-offset: 0.1em;
}
::target-text::target-text {
background-color: rebeccapurple;
color: white;
}
Transition between different DOM states
figcaption {
view-transition-name: figure-caption;
}
::view-transition-old(figure-caption),
::view-transition-new(figure-caption) {
animation-duration: 0.5s;
}
Advanced CSS value manipulation
el.attributeStyleMap.set('padding', CSS.px(42));
const padding = el.attributeStyleMap.get('padding');
console.log(padding.value, padding.unit); // 42, 'px'
accent-colorProvides an accent color for form elements
form {
accent-color: seagreen;
}
color-schemeForces a color scheme onto elements
:root {
color-scheme: dark;
}
content-visibilityControls whether the contents of an element are visible
section {
content-visibility: auto;
}
touch-action.box {
touch-action: pan-right pinch-zoom;
}
clip-path: path().box {
clip-path: path("M 20 240 C 20 0 300 0 300 240 Z");
}
Basic styling of scrollbars
.container {
scrollbar-gutter: stable;
scrollbar-width: thin;
scrollbar-color: firebrick;
}
Defines and applies custom color palettes for COLRv1 fonts
@font-palette-values --Grays {
font-family: Rocher;
base-palette: 9;
override-colors: 2 rgb(90, 290, 210);
}
.grays {
font-family: "Rocher";
font-palette: --Grays;
}
Math functions and units related to trigonometry
.box {
width: calc(pow(2% / 4));
height: calc(tan(60deg) * 100%;
}
Mathematical functions related to exponential functionality
pow(), exp(), hypot(), log(), rem(), sqrt(), abs(), round(), sign()
.box {
width: calc(10px * pow(5, 2));
height: calc(10px * exp(1));
}
scroll-behaviorDefines whether the scroll behavior is smooth or immediate
article {
scroll-behavior: smooth;
}
overscroll-behaviorControls the effect when overscrolling a scroll container
.box {
overflow-behavior: contain;
}
scroll-margin + scroll-paddingDefines the distance of elements to their scroll container
article {
scroll-padding: 150px;
}
p {
scroll-margin: 150px;
}
margin-trimControls trimming of margins
article > p {
margin-trim: block;
}
text-wrapInfluences text wrapping e.g. to balance it out
article > p {
text-wrap: balance;
}
cap, ic, lh, rex, rch, ric, rlh
p {
font-size: 1.5cap;
}
input {
height: 2lh;
}
:nth-child(an + b of S)Matches elements based on their position in a group of siblings matching a selector
p:nth-child(2n + 1 of .special) {
color: red;
}
:picture-in-pictureMatches elements that are displayed in a picture-in-picture context
video:picture-in-picture {
border: 2px solid blue;
border-radius: 4px;
}
:fullscreenMatches elements that are displayed in fullscreen mode
video:fullscreen {
border: 2px solid blue;
}
hyphenate-limit-charsDefines the minimum number of characters in a hyphenated word
p {
hyphenate-limit-chars: 3;
}
scroll-snap-stopDefines whether a scroll container should stop on snap points
.gallery {
scroll-snap-stop: always;
}
Allows to define custom highlights
CSS.highlights.set('my-custom-highlight', highlight);
::highlight(my-custom-highlight) {
background-color: yellow;
color: black;
}
Scroll-driven animationsAnimating elements based on scroll position
@keyframes --stretch {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
body {
scroll-timeline: --scroll-indicator;
}
#scroll-indicator {
position: fixed;
top: 0;
background-color: firebrick;
width: 100%;
height: 8px;
animation: --stretch 1s linear;
animation-timeline: --scroll-indicator;
}
Anchor PositioningPositions elements relative to other elements with fallbacks
.anchor {
anchor-name: --my-anchor;
}
.tooltip {
position: absolute;
bottom: anchor(--my-anchor auto);
top: auto;
}
@scopeScopes styles to a DOM subtree
@scope (.card) {
p {
background-color: lime;
}
View Transitions for MPATransitions between two elements in multi-page applications
@keyframes --slide-to-left {
from { transform: translateX(100vw); }
to { transform: translateX(0); }
}
::view-transition-old(root) {
animation: none;
}
::view-transition-new(root) {
animation: --slide-to-left 0.3s;
}
@starting-styleDefines initial styles for elements being added
div {
width: 100px;
height: 100px;
transition: background-color 0.5s;
background-color: transparent;
@starting-style {
background-color: yellow;
}
}
Pinterest-like layout
.container {
display: grid;
gap: 10px;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
grid-template-rows: masonry;
}
Defines the color space to use for transitioning colors in a gradient
.card {
background-image: linear-gradient(in lch, yellow, blue);
}
contrast-color()Selects a fitting contrast color for a given color
.card {
background-color: #000;
color: contrast-color(#000 vs green, blue, yellow);
}
toggle()Toggles between different values
ul {
list-style-type: toggle(disc; circle; square; box);
}
box-shadow-* longhand propertiesDifferent box-shadow-* properties for the different parts of box shadows
.container {
box-shadow-offset: 4px 6px;
box-shadow-color: rgb(0 0 0 / 0.4);
box-shadow-blur: 5px;
box-shadow-spread: 0;
box-shadow-position: inset;
}
stripes()Defines a 1d image that can be used in different contexts like multi-color borders
.container {
border: 10px solid stripes(red 1px, green 2fr, blue 2px);
}
border-*-radius longhand propertiesBorder properties that allow to set the two radii for one side
.container {
border-top-radius: 10px;
}
.container {
border-inline-end-radius: 10px;
}
Please take the State of CSS 2023 survey!
https://stateofcss.com/en-us/