10 CSS Tips You Must Know About in 2024
Add to your RSS feed5 September 20249 min readTable of Contents
CSS continues to evolve, offering new tools and techniques for web designers and developers to create visually stunning and highly functional websites. Staying up to date with the latest trends and best practices is essential. Here are 10 CSS tips you must know about in 2024 to enhance your web development skills and create cutting-edge designs.
Check also 10 HTML Tips You Must Know About in 2024.
1. The :has() pseudo-class Selector
The :has() pseudo-class selector is a powerful addition to CSS, allowing you to style elements based on their descendants or other specific conditions within them. This selector enables you to apply styles to a parent element if it contains certain child elements or meets specific criteria. For example, you can highlight a div that contains an image or change the background of a list item that has a link. The :has() selector greatly enhances the flexibility and specificity of CSS, making it easier to create dynamic, conditionally styled layouts.
Example - Card hover with :not() Selector
- Create index.html and style.css files:
index.html
1 <!DOCTYPE html>2 <html lang="en">3 <head>4 <meta charset="UTF-8" />5 <meta name="viewport" content="width=device-width, initial-scale=1.0" />6 <title>Document</title>7 <link rel="stylesheet" href="style.css" />8 </head>9 <body>10 <div class="cards">11 <div class="card"></div>12 <div class="card"></div>13 <div class="card"></div>14 <div class="card"></div>15 <div class="card"></div>16 <div class="card"></div>17 </div>18 </body>19 </html>
style.css file:
1 .cards {2 display: flex;3 gap: 1rem;4 }5 .card {6 width: 100%;7 height: 300px;8 background-color: rgb(12, 22, 164);9 transition: opacity 0.4s ease;10 }11 .cards:hover > :not(:hover) {12 opacity: 0.5;13 }
Now we have a six cards inside a flex container
- Add hover to them
1 .cards:hover > :not(:hover) {2 opacity: 0.5;3 }
Now we have a bug. If you hover between the cards, all cards will have an opacity of 0.5, and none will be selected. To fix it add visibile to the .card selector
1 .cards {2 display: flex;3 gap: 1rem;4 visibility: hidden;5 }6 .card {7 visibility: visible;8 width: 100%;9 height: 300px;10 background-color: rgb(12, 22, 164);11 transition: opacity 0.4s ease;12 }13 .cards:hover > :not(:hover) {14 opacity: 0.5;15 }
2. The :focus-within pseudo-class
The CSS :focus-within selector is a powerful tool that allows you to apply styles to a parent element when any of its child elements receive focus. This is particularly useful for enhancing user interaction with forms, menus, and interactive components. By using :focus-within, you can highlight or style entire sections of your page when users navigate through them using a keyboard or mouse, improving accessibility and user experience.
As we know, the traditional method for creating custom radio buttons involved using the adjacent sibling combinator (+). You’re probably familiar with it. However, modern CSS features now offer a different and more efficient approach.
Example: Radio Buttons with :focus-within
- Create a html and css files:
index.html
1 <!DOCTYPE html>2 <html lang="en">3 <head>4 <meta charset="UTF-8" />5 <meta name="viewport" content="width=device-width, initial-scale=1.0" />6 <title>Document</title>7 <link rel="stylesheet" href="style.css" />8 </head>9 <body>10 <div class="radio-button">11 <input id="rb-1" class="radio-button__input sr-only" type="radio" name="radio" checked />12 <label for="rb-1" class="radio-button__label">Example 1</label>13 </div>14 <div class="radio-button">15 <input id="rb-2" class="radio-button__input sr-only" type="radio" name="radio" />16 <label for="rb-2" class="radio-button__label">Example 2</label>17 </div>18 </body>19 </html>
style.css
1 body {2 display: flex;3 justify-content: center;4 align-items: center;5 height: 90vh;6 }78 .sr-only {9 width: 1px;10 height: 1px;11 clip-path: inset(50%);12 overflow: hidden;13 position: absolute;14 white-space: nowrap;15 }1617 .radio-button {18 --radio-button-size: 1rem;19 --radio-button-gap: 1rem;20 --radio-button-dot-size: 0.5rem;2122 display: inline-flex;23 align-items: center;24 position: relative;25 isolation: isolate;26 }2728 .radio-button::before {29 content: '';30 box-sizing: border-box;31 width: var(--radio-button-size);32 height: var(--radio-button-size);3334 border: 1px solid #242424;35 border-radius: 100%;36 position: absolute;37 z-index: -1;38 }3940 .radio-button__label {41 display: grid;42 padding-left: calc(var(--radio-button-dot-size) + var(--radio-button-gap));43 }4445 .radio-button__label::before,46 .radio-button__label::after {47 content: '';48 border-radius: 100%;49 opacity: 0;5051 position: absolute;52 align-self: center;53 left: var(--radio-button-dot-size);54 transform: translateX(-50%);55 scale: 0;56 transform-origin: left center;57 }5859 .radio-button__label::before {60 border-top: var(--radio-button-dot-size) solid #242424;61 border-left: var(--radio-button-dot-size) solid #242424;62 transition: 0.3s;63 }6465 .radio-button__label::after {66 width: var(--radio-button-dot-size);67 height: var(--radio-button-dot-size);6869 background-color: #2500e0;70 transition: 0.6s;71 }
We’ve created simple buttons, and now there’s just one final step. We need to write the code for the states when the radio button is focused or selected. As I mentioned earlier, this will be based on the adjacent sibling combinator (+).
1 .radio-button__input:checked + .radio-button__label::before {2 opacity: 1;3 scale: 1;4 }56 .radio-button__input:focus + .radio-button__label::after {7 scale: 3.6;8 opacity: 0.2;9 }
What's the issue? If, in the markup, the element with the class .radio-button__input accidentally stops being placed before the .radio-button__label element, the styling will break completely. This is the downside of relying on the adjacent sibling combinator (+).
The modern CSS doesn't have this bug because it relies on the :has() and :focus-within pseudo-classes.
- Add :focus-within selector
1 .radio-button:has(:checked) .radio-button__label::before {2 opacity: 1;3 scale: 1;4 }56 .radio-button:focus-within .radio-button__label::after {7 scale: 3.6;8 opacity: 0.2;9 }
3. The inset Property
Sometimes, elements with the position property set to absolute are used to stretch an element across all available space. The most common code for this looks like:
1 .parent {2 position: relative;3 }45 .parent::before {6 content: '';7 width: 100%;8 height: 100%;910 position: absolute;11 top: 0;12 left: 0;13 }
This snippet is outdated because it can be simplified. The inset property allows you to set the coordinates for all four sides of an element at once, replacing the need for top, right, bottom, and left.
To update the example, you can remove the width and height properties. Since .parent has position: absolute, its size can be determined by the specified offsets.
In this case, we’ll use inset: 0 to achieve the same effect.
1 .parent {2 position: relative;3 }45 .parent::before {6 content: '';7 position: absolute;8 inset: 0;9 }
4. CSS Variables
CSS Variables, also known as custom properties, are a powerful feature that allows you to store and reuse values throughout your stylesheet. They enable you to define values like colors, fonts, or dimensions in one place, making your code more maintainable and flexible.
When coding a project, it's common to write a lot of rules inside media queries, which can make the code difficult to navigate. To illustrate this problem, I’ll provide styles for two elements with the classes .heading and .description.
1 .heading {2 font-size: 2rem;3 }45 .description {6 font-size: 0.75rem;7 }89 @media (min-width: 641px) {10 .heading {11 font-size: 3rem;12 }1314 .description {15 font-size: 1.25rem;16 }17 }1819 @media (min-width: 1025px) {20 .heading {21 font-size: 3.5rem;22 }2324 .description {25 font-size: 1.5rem;26 }27 }
Previously, we had to write separate rules for every property change. For instance, to adjust the font-size in each media query, we needed two rules for both .heading and .description. This approach was inefficient before custom properties came along.
Now, with custom properties, we can set base values and modify them inside media queries using a parent element. This way, we only need one rule per media query instead of many.
1 .heading {2 font-size: var(--heading-font-size, 2rem);3 }45 .description {6 font-size: var(--hint-font-size, 0.75rem);7 }89 @media (min-width: 648px) {10 .text {11 --heading-font-size: 3rem;12 --hint-font-size: 1.25rem;13 }14 }1516 @media (min-width: 1280px) {17 .text {18 --heading-font-size: 3.5rem;19 --hint-font-size: 1.5rem;20 }21 }
5. place-items property
For a long time, the transform property has been the go-to method for centering an element with position: absolute. The technique involves two key steps.
First, move the element 50% away from the top and left edges using the top and left properties. Then, apply translate(-50%, -50%) to shift it back by half of its width and height.
1 .elem {2 width: 200px;3 height: 200px;4 position: relative;5 }67 .elem::before {8 width: 22px;9 height: 22px;1011 position: absolute;12 top: 50%;13 left: 50%;14 transform: translate(-50%, -50%);15 }
Today, there's a simpler method available. We can use the place-items property.
1 .elem {2 width: 20rem;3 height: 20rem;45 display: grid;6 place-items: center;7 }89 .elem::before {10 width: 2rem;11 height: 2rem;12 position: absolute;13 }
6. scrollbar-gutter property
The scrollbar-gutter property provides control over the space allocated for scrollbars in your layout. This property helps manage how scrollbars impact the layout, especially when it comes to accommodating their width and avoiding layout shifts when they appear or disappear.
It ensures that space is reserved for scrollbars, preventing content from shifting when the scrollbar appears.
1 body {2 scrollbar-gutter: stable;3 }
7. system-ui fonts
Now you can change something like this:
1 body {2 font-family: var(3 --main-font,4 -apple-system,5 BlinkMacSystemFont,6 Segoe UI,7 Roboto,8 Open Sans,9 Ubuntu,10 Fira Sans,11 Helvetica Neue,12 sans-serif13 );14 }
to:
1 body {2 font-family: var(--main-font, system-ui);3 }
8. :lang() pseudo class
How to Use :lang() Pseudo-Class
Syntax:
1 :lang(en) {2 font-style: italic;3 }
language specifies the language code (e.g., en, fr, de).
Example Usage
1 :lang(fr) {2 font-family: 'Courier New', monospace;3 text-align: center;4 }
HTML Example:
1 <p lang="en">This is an English paragraph.</p> <p lang="fr">Ceci est un paragraphe en français.</p>
Combine :lang() pseudo class with :not()
1 :not(:lang(fr)) {2 font-style: italic;3 }
In the HTML above, the paragraphs will be styled according to their language attribute, demonstrating how the :lang() pseudo-class can be used to handle language-specific styling effectively.
9. aspect-ratio property
The aspect-ratio property in CSS is a powerful tool that allows you to control the aspect ratio of an element, ensuring it maintains a specific ratio between its width and height. This property is especially useful for responsive design, maintaining the proportion of elements across various screen sizes.
Syntax:
1 .img {2 aspect-ratio: 1/3;3 }
Example Usage
1 .media {2 aspect-ratio: 12 / 8; /* Width is 12 units for every 8 units of height */3 width: 100%;4 background-color: 'red';5 }
By using the aspect-ratio property, you can create more flexible and responsive designs, ensuring elements maintain their proportions across different devices and screen sizes.
10. :is() pseudo-class
The :is() pseudo-class in CSS simplifies applying styles to multiple selectors by allowing you to group them together in a single rule. This makes your CSS more readable and easier to manage, especially when you need to apply the same styles to various elements.
Example Usage
Syntax:
1 :is(h1, h2, h3) {2 text-transform: uppercase;3 }
In this example, all h1, h2, and h3 elements will have uppercase text.
Combining with Other Selectors
1 :is(.button, .link) {2 color: white;3 padding: 1rem;4 }
:is() reduces repetition by allowing you to group multiple selectors together.
By mastering these 10 CSS tips, you'll be well-equipped to create modern, responsive, and dynamic web designs in 2024. Whether you’re building a personal project or working on a client site, these tips will help you write cleaner, more efficient CSS that stands out.