Guides

Three modern CSS properties your website must have

1. Scroll-margin

Ever used an anchor link on a webpage, trying to find something, but got totally lost? It happens way too often. Usually the target elements like headings go behind a fixed header.

[@portabletext/react] Unknown block type "video", specify a component for it in the `components.types` prop

There's a CSS property called scroll-margin in CSS that can help us with this problem. By setting scroll-margin-top equal to a value around the height of the fixed header, we can fix this issue:

h2:target {
  scroll-margin-top: var(--header-height);
}

But, what if we want to make this trick work for <h3> or <h4> too? Simple! We use the :is selector to cover all bases:

:is(h2, h3, h4):target {
  scroll-margin-top: var(--header-height);
}

Also, we can play around with units like ex, or lh for dynamic spacing:

:target {
  scroll-margin-top: calc(var(--header-height) + 1lh);
}

This way, we get different offset based on the line-height of the target element which makes our spacing more dynamic.

2. color-scheme

Have you seen a website with a dark mode, but the scrollbar's still shining bright? Annoying, right? That's where color-scheme in CSS comes to the rescue.

[@portabletext/react] Unknown block type "video", specify a component for it in the `components.types` prop

By setting color-scheme to dark light, you're telling the browser that your page can handle both dark and light modes. Plus, you can get granular, applying it to specific elements or the entire document.

:root {
	color-scheme: dark light;
}

You can also use a meta tag for applying color-scheme to your document.

<meta name="color-scheme" content="light dark">

The advantage of using a meta tag is that the browser knows your preferences before loading your website's CSS.

Be cautious though – using it on the root element or a meta tag affects the whole document!

Usually, the best approach is to pair this property with the prefers-color-scheme media feature. This gives you complete control over where you want to make changes based on the user's preferences.

@media (prefers-color-scheme: dark) {
  form {
    color-scheme: dark;
  }
}

Usually, websites switch between dark and light themes by assigning a class like dark or light to the body of the document. However, in our case, fixing the scrollbar requires applying the color-scheme property directly to the root element. Can we tackle this with CSS alone? Enter the :has() selector.

:root:has(body.dark) {
  color-scheme: dark;
}
[@portabletext/react] Unknown block type "newsletter", specify a component for it in the `components.types` prop

3. text-wrap

Have you ever seen titles or captions that seem oddly wrapped, ending with a single word on the last line? It's not just a style preference; our eyes genuinely prefer titles with equal-length lines – it looks cleaner and feels better to read.

We can use text-wrap property with the value of balance to have well-balanced titles on our website:

h2 {
  text-wrap: balance;
}

You can see the effect of this property on the blog post titles in the following image. The right picture is where I applied the balance value:

This great feature doesn’t discriminate against browsers. It’s a progressive enhancement, meaning it works great in modern setups while gracefully degrading in older ones.

The video

Want more examples and demos? Watch me break down these three properties on YouTube:

[@portabletext/react] Unknown block type "iframe", specify a component for it in the `components.types` prop