How to fix CSS issues with :before not working

Fixes for :before pseudo elements not working with your CSS. We will go over a checklist on how to do this.

Dec 2, 2022 | Read time 6 minutes

🔔 Table of contents

What is css selectors and how to use it | web development course | tutorial no 15.

If you are experiencing issues with the :before pseudo element in CSS, there are a few potential fixes you should consider.

1. Check the syntax: First and foremost, make sure that you are entering the correct syntax for the :before pseudo element, as there are slight variations between different browsers. Generally speaking, the syntax should look similar to this:

p::before { /* we are using <p> here, but it can be any element*/
  content: ''; 
}

2. Include a content property: The content property is essential for the :before pseudo element to work properly. Without the content property, it may not appear.

3. Check the you are using the right HTML tag: Tags that are classified as replaced elements will not work with :before. These include - <audio>, <canvas>, <embed>, <iframe>, <img>, <input>, <object>, <video>

4. Check for CSS specificity issues: If you are using multiple elements with the :before pseudo element, you may be encountering specificity issues where the declarations in one block of code are overriding the declarations in another. To avoid this, you can use the !important declaration to make a style more specific and ensure that it is not overridden.

5. Check the browser support: As mentioned previously, different browsers may have slightly different syntax requirements for the :before pseudo element. Make sure to double-check the syntax to ensure that it is supported in the browser that you are using.

Check the syntax

The :before pseudo element (when combined with the content property) creates a child element before the element’s contents. To use the :before property, the usual syntax is as as follows.

p::before { /* we are using <p> here, but it can be any element*/
  content: ''; 
}

We can use the two colon version ::before or the single colon version :before. The difference is that the double colons (::before) was introduced by CSS 3 since it also introduced both pseudo elements and pseudo classes. Therefore it needed away to distiguish between the two.

Most modern browsers support both versions. Support for the double colon ::before is not available for IE versions (eg IE11 or less)

Not using the content property

A common reason of why your :before is not working is that you are not specify the content property. We need to delare content:"". For example, the following will not work:

.my-element::before {
  background: red;
  width: 100px;
  height: 100px;
}
.my-element::before {
  content: ""; /* :before will only appear if this content is declared */
  background: red;
  width: 100px;
  height: 100px;
}

Check the you are using the right HTML tags

Another consideration when using the :before pseudo element is the HTML tag you are applying that for.

According to the HTML specificiation (https://html.spec.whatwg.org/multipage/rendering.html#replaced-elements) - the following elements can be replaced elements:

  • <audio>
  • <canvas>
  • <embed>
  • <iframe>
  • <img>
  • <input>
  • <object>
  • <video>.

Replaced elements are HTML elements in which the browser will replace the content. Therefore, whatever we have declared with the :before will be replaced. Take the following example with <img>. This will not work since img is a replaced HTML element.

img::before { /* will not work because its a replaced element */
  content: "before";
}
img::after { /* will not work because its a replaced element */
  content: "after";
}

More information can be found here: https://developer.mozilla.org/en-US/docs/Web/CSS/Replaced_element

Check CSS specifity issues

We need to check to see if the :before declaration for our element is being overridden by another CSS rule somewhere else further down the CSS file. As an example, lets take the following CSS:

p::before { 
  content: "BB";
}

...
...

p::before { /* This will override the previous declaration */
  content: "AA";
}

In the above, our p will have :before content of “AA” (overwritting “BB”). If two declarations that targat the same element, the style that is further down the CSS file will win. In these cases we can use the !important property, but use it carefully.

Check browser support

There are limitations on the use of the :before pseudo elements - so we need to consider browser combatbility. Some common issues include:

  • IE9, IE10, IE11 ignore CSS rem units in the line-height property
  • Firefox & Edge do not support :after and :before for input fields
  • Animation and transition support limited on IE, Safari and Safari Mobile. Chrome supports this as of version 26.
  • IE8 only supports the single-colon CSS 2.1 syntax (i.e. :pseudo-class). It does not support the double-colon CSS3 syntax

Summary

This post went through various reasons why :before is not working in your CSS and HTML design. The reasons range from:

  • Not using the content property as intended.
  • The syntax is not correct (eg using ::before vs :before)
  • Not using valid HTML tags that support the :before property. HTML tags that are replaced elements will not work with :before!
  • Check for browser support - IE versions will only support the single colon :before - since this is part of CSS2.
  • Check for CSS specifity issues - having two CSS styles that target the same element will cause this issue. The style that is declared lower on the CSS file will take effect over the other!

Hopefully the above checks will fix your CSS :before problems!

👋 About the Author

G'day! I am Huy a software engineer based in Australia. I have been creating design-centered software for the last 10 years both professionally and as a passion.

My aim to share what I have learnt with you! (and to help me remember 😅)

Follow along on Twitter , GitHub and YouTube