20 Pro CSS Tips to Up Your Game

Front-end development is quickly becoming more and more focused on efficiency – faster loading and rendering through selector choice and minimizing code. Pre-processors like Less and SCSS go a long way in doing some of the work for us, but there are plenty of ways to write minimal, quick CSS the native way. This guide covers 20 Pro CSS Tips to help you cut down on duplicate rules and overrides, standardize the flow of styling across your layouts and will help you create a personal starting framework that is not only efficient, but solves many common problems.

If you’re relatively new to CSS, check out The Power of CSS Selectors and How to Use Them for a thorough primer on many of the super-selectors featured here.

1 – Use a CSS Reset

CSS reset libraries like normalize.css have been around for years, providing a clean slate for your site’s styles that help ensure better consistency across browsers. Most projects don’t really need all of the rules these libraries include, and can get by with one simple rule to remove all the margins and paddings applied to most elements in your layout by the browser’s default box-model:

* {    
  box-sizing: border-box;   
  margin: 0;    
  padding: 0;  

Using the box-sizing declaration is optional – if you follow the Inherit box-sizing tip below, you can skip it.

2 – Inherit box-sizing

Let box-sizing be inherited from html:

html {    
    box-sizing: border-box;  
*, *:before, *:after {    
    box-sizing: inherit;  

This makes it easier to change box-sizing when code is introduced through 3rd party plugins or applications that use different behavior.

3 – Get Rid of Margin Hacks With Flexbox

How many times have you tried designing a grid, such as a portfolio or image gallery, where you used floats and then had to clear them or reset margins to get the columns to break into the number of rows you want? Get rid of nth-, first-, and last-child hacks by using the space-between property value in flexbox:

.flex-container {    
    display: flex;   
    justify-content: space-between;  
.flex-container .item {    
    flex-basis: 23%;  

Now column gutters always appear evenly-spaced. Learn more about flexbox with Master CSS Flexbox in 5 Simple Steps

4 – Use :not() to Style Borders on Lists

A very common practice in web design has been to use :last-child or :nth-child selectors to undo a style previously declared on the parent selector. Think of a navigation menu that uses borders to create a separator between each link, and the second rule added to take that border off the end:

.nav li {    
    border-right: 1px solid #666;  
.nav li:last-child {    
    border-right: none;  

This is quite messy as it not only forces the browser to render things one way, then undo it for a specific selector. Resetting styles this way is sometimes unavoidable, but for the most part, you can use the :not() pseudo-class to only apply a style to the elements you want in one single statement:

.nav li:not(:last-child) {    
    border-right: 1px solid #666;  

This says, put a border on all the .nav list items except the last one. Simple!

Sure, you can also use .nav li + li or even .nav li:first-child ~ li, but :not() will always be more semantic and easy to understand.

5 – Add line-height to body

The one thing that leads to inefficient stylesheets is repeating declarations over and over again. The better you get at planning your project and combining rules, the more fluid your CSS will be. One way to do this is understanding the cascade and how the styles you write for general selectors can be inherited elsewhere. Line height is one property you can set for your entire project, not only to minimize lines of code but to enforce a standard look to your site’s typography.

Rather than add line-height to each <p>, <h*> and so on, add it to body:

body {    
    line-height: 1.5;  

Note we don’t declare a unit here – we just tell it to make the line height one and a half times more than the font size for the rendered text.

6 – Vertically-Center Anything

Setting a global rule to vertically center your layout is a great way to set a foundation for elegantly set content layouts where you’re not ready to use CSS Grid.

html, body {    
    height: 100%;    
    margin: 0;  
body {    
    -webkit-align-items: center;    
    -ms-flex-align: center;    
    align-items: center;    
    display: -webkit-flex;    
    display: flex;  

We go into detail about all the ways you can vertically center things in CSS Vertical Centering Everything You Need To Know

7 – Use SVG for Icons

SVG scales well for all resolution types and is supported in all browsers. So ditch your .png, .jpg, or .gif-jif-whatev files. Even FontAwesome now offers SVG Icon Fonts in FontAwesome 5. Setting SVG works just like any other image type:

.logo {    
    background: url("logo.svg");  

Accessibility tip: If you use SVGs for intractable elements such as buttons, and the SVG fails to load, a rule like this one will help maintain accessibility (make sure it has the appropriate aria attributes set in the HTML):

.no-svg .icon-only:after {    
    content: attr(aria-label);  

WordPress tip: Don’t use SVG via builders or plugins that want to store them in the Media Library, as it introduces security concerns.

8 – Use the “Owl” Selector

Using the universal selector (*) with the adjacent sibling selector (+) provides a powerful CSS capability that allows us to set rules for all elements in the flow of the document that specifically follow other elements:

* + * {    
    margin-top: 1.5rem;  

This is another great trick that can help you create more uniform type and spacing. In the example above, all elements that follow other elements, like an H4 that follows an H3, or a paragraph following another paragraph, will each have at least 1.5rems of space (equal to about 30px.)

9 – Consistent Vertical Rhythm

Consistent vertical rhythm provides a visual aesthetic that makes content far more readable. Where the owl selector may be too general, use a universal selector (*) within an element to create a consistent vertical rhythm for specific sections of your layout:

.intro > * {   
   margin-bottom: 1.25rem;  

10 – Use box-decoration-break For Prettier Wrapped Text

Say you want to apply uniform spacing, margins, highlights or background colors to long lines of text that wrap to more than one line, but don’t want the whole paragraph or heading to look like one large block. The box-decoration-break property allows you to apply styles to just the text while keeping padding and margins intact. This is particularly useful if you want to apply highlights on hover, or style sub-text in a slider to have a highlighted look:

.p {
  display: inline-block;
  box-decoration-break: clone;
  -o-box-decoration-break: clone;
  -webkit-box-decoration-break: clone;

The inline-block declaration allows the colors, backgrounds, margins and padding to be applied to each line of text rather than the entire element, and the clone declaration makes sure those styles are applied consistently to each line equally.

11 – Equal-Width Table Cells

Tables can be a pain to work with so try using table-layout: fixed to keep cells at equal width:

.calendar {    
    table-layout: fixed;  

12 – Force Empty Links to Show with Attribute Selectors

This is especially useful for links that are inserted via a CMS, which don’t usually have a class attribute and helps you style them specifically without generically affecting the cascade. For example, the <a> element has no text value but the href attribute has a link:

a[href^="http"]:empty::before {    
    content: attr(href);  

13 – Style “Default” Links

Speaking of link styling, you can find a generic a style in just about every stylesheet. This forces you to write additional overrides and style rules for any links in a child element, and when working with a CMS like WordPress can lead to problems with your king link style trumping a button text color, for example. Try this less-intrusive way to add a style for “default” links:

a[href]:not([class]) {    
    color: #999;    
    text-decoration: none;  
    transition: all ease-in-out .3s;

Now the style will only apply itself to links that otherwise have no other style rule.

14 – Intrinsic Ratio Boxes

To create a box with an intrinsic ratio, all you need to do is apply top or bottom padding to a div:

.container {    
    height: 0;    
    padding-bottom: 20%;    
    position: relative;  
.container div {    
    border: 2px dashed #ddd;    
    height: 100%;    
    left: 0;    
    position: absolute;    
    top: 0;    
    width: 100%;  

Using 20% for padding makes the height of the box equal to 20% of its width. No matter the width of the viewport, the child div will keep its aspect ratio (100% / 20% = 5:1).

15 – Style Broken Images

This tip is less about code reduction and more about refining the detail of your designs. Broken images happen for a number of reasons, and are either unsightly or lead to confusion (just an empty element). Create more aesthetically-pleasing with this little bit of CSS:

img {    
    display: block;    
    font-family: Helvetica, Arial, sans-serif;    
    font-weight: 300;    
    height: auto;    
    line-height: 2;    
    position: relative;    
    text-align: center;    
    width: 100%;  
img:before {    
    content: "We're sorry, the image below is missing :(";    
    display: block;    
    margin-bottom: 10px;  
img:after {    
    content: "(url: " attr(src) ")";   
    display: block;    
    font-size: 12px;  

16 – Use rem for Global Sizing; Use em for Local Sizing

After setting the base font size at the root, for example html{font-size: 15px;}, you can set font-size for containing elements to rem:

article {    
    font-size: 1.25rem;  
aside {    
    font-size: .9rem;  

Then set the font size for textual elements to em:

h2 {    
    font-size: 2em;  
p {    
    font-size: 1em;  

Now each containing element becomes compartmentalized and easier to style, more maintainable, and flexible.

17 – Hide Autoplay Videos That Aren’t Muted

This is a great trick for a custom user stylesheet when working with content you can’t easily control from the source. This trick will help you avoid annoying your visitors with sound from an auto-playing video when the page is loaded, and again features the wonderful :not() pseudo-selector:

video[autoplay]:not([muted]) {    
    display: none;  

18 – Use :root for Flexible Type

The font size in a responsive layout should be able to adjust to the viewport automatically, saving you the work of writing media-queries just to deal with font sizing. You can calculate the font size based on the viewport height and width using :root: and viewport units:

:root {    
    font-size: calc(1vw + 1vh + .5vmin);  

Now you can utilize the root em unit based on the value calculated by :root:

body {    
    font: 1rem/1.6 sans-serif;  

Combine this with the rem/em trick above for greater control. See CSS Fix for iOS vh-unit Bug for tips on managing older versions of Safari.

19 – Set font-size on Form Elements for a Better Mobile Experience

To avoid mobile browsers (iOS Safari, etc.) from zooming in on HTML form elements when a <select> drop-down is tapped, add font-size to the input styles:

textarea {    
    font-size: 16px;  

20 – Use CSS Variables!

Last but not least, the most powerful CSS level-up comes from CSS variables, which allow you to declare a set of common property values that can be reused via a keyword anywhere in the stylesheet. Your brand may have a set of colors to be used across the project to keep things consistent. Repeating these color values over and over again in your CSS is not only a chore, but also error prone. If a color needs to be changed at some point, your forced to find-and-replace, which is not reliable or fast, and when building products for end-users, variables make customization that much easier. For example:

:root {
  --main-color: #06c;
  --accent-color: #999;

h1, h2, h3 {
  color: var(--main-color);
footer span{
 color: var(--accent-color);

Learn more about CSS Variables on the MDN