Have you ever wanted to add a small icon before a menu item… but didn’t want to clutter your HTML with extra elements?

Or maybe you were styling a WordPress page and thought, “There must be a cleaner way to add decorative images or overlays without editing the markup.”

You’re not alone. Many developers, bloggers, and WordPress users run into this exact challenge when trying to enhance UI elements, add visual cues, or style components using CSS alone.

That’s where the CSS ::before pseudo-element becomes incredibly powerful.

With just a few lines of CSS, you can insert icons, decorative graphics, or even full background images before an element, without adding a single extra HTML tag.

In this guide, you’ll learn:

  • What the CSS ::before pseudo-element actually does
  • How to insert images using content and background-image
  • Practical code examples and real-world use cases
  • Common mistakes and troubleshooting tips
  • How to use this technique inside WordPress, Elementor, and Gutenberg

By the end, you’ll know exactly how to add images using ::before and use it confidently in real projects.

Let’s start with the basics.

What Is the CSS ::before Pseudo-Element?

Setting an image in CSS ::before means using the ::before pseudo-element together with the content property or background-image property to insert a visual element before an HTML element’s content. This technique allows developers to add icons, decorative graphics, or overlays without modifying the HTML structure.

In simple terms, the ::before pseudo-element creates a virtual element that appears before the content of an HTML element. Because it’s generated through CSS, it doesn’t exist in the HTML markup itself.

Developers often use it to:

  • Add icons before text
  • Insert decorative graphics
  • Create background overlays
  • Style UI components without extra HTML

Now let’s see how images can actually be added using this technique.

Can You Add Images with CSS ::before?

Yes, you can add images using the CSS ::before pseudo-element, and it’s a surprisingly useful technique when you want to enhance an element visually without modifying the HTML structure.

Instead of inserting another <img> tag into your markup, the ::before pseudo-element allows you to generate a visual element directly through CSS. This works by attaching the pseudo-element to an existing HTML element and controlling its appearance using properties like the content property, background-image, CSS selectors, and positioning rules.

Developers often use this approach to:

  • Add icons before text (such as menu items or feature lists)
  • Insert decorative graphics without extra HTML elements
  • Create overlays or background effects
  • Style UI components while keeping HTML clean and semantic

In practice, there are two primary ways to display images with the ::before pseudo-element.

Two Common Methods

  1. Using content: url()

    This method directly inserts an image into the pseudo-element.

    .item::before {
      content: url(“icon.png”);
    }

    It works well for small inline visuals, such as icons or indicators placed before text.
  2. Using background-image

    This approach creates the pseudo-element first and then applies an image as its background.

    .box::before {
      content: “”;
      background-image: url(“image.jpg”);
    }

    It’s more flexible and is commonly used for decorative backgrounds, overlays, and layered effects, especially when combined with CSS positioning and z-index.

When to Use Each Method

MethodBest Use Case
content: url()Inline icons or small decorative images
background-imageBackground visuals, overlays, or design elements

Because the second method gives you greater control over CSS layout, scaling, and positioning, it’s usually the preferred option for more complex designs.

Important Limitations to Understand

Before you start using images with ::before, there are a few key rules to keep in mind.

  • The content property is required.
    Without it, the ::before pseudo-element will not render.
  • It does not work on replaced HTML elements.
    Elements like <img>, <video>, or <iframe> cannot use ::before.
  • Images inserted with CSS are typically decorative.
    Because they are not part of the HTML document structure, screen readers and search engines may ignore them.

For this reason, pseudo-element images are best used for visual enhancements rather than meaningful content.

Now that you understand the basics, let’s take a closer look at the first method for inserting images using content: url().

Method 1: Adding an Image Using content: url()

The simplest way to insert an image with the ::before pseudo-element is by using the CSS content property.

Basic Example

.icon::before {

  content: url(“icon.png”);

}

This code inserts the image before the element’s content.

Example with Spacing and Alignment

.menu-item::before {

  content: url(“icon.png”);

  display: inline-block;

  margin-right: 8px;

  vertical-align: middle;

}

What’s Happening Here?

  • content inserts the image
  • display: inline-block allows spacing and alignment
  • margin-right creates space between icon and text
  • vertical-align aligns the icon with text

When This Method Works Best

Use content: url() when you want to:

  • Add icons before text
  • Insert small decorative images
  • Create UI markers like arrows or checkmarks

Limitation

Images inserted this way cannot easily be resized, which leads us to a more flexible approach.

Method 2: Adding an Image Using background-image

If you want more control over how an image looks and behaves, using the background-image property with the CSS ::before pseudo-element is usually the better approach.

Unlike content: url(), which simply inserts an image inline, background-image lets you control the size, positioning, and layering of the image using standard CSS layout properties. This makes it ideal for creating decorative backgrounds, overlays, and UI effects without adding extra HTML elements.

Basic Example

.box::before {

 content: “”;

 background-image: url(“image.jpg”);

}

Here’s what happens in this code:

  • content: “” creates the ::before pseudo-element.
  • background-image applies the image to that pseudo-element.
  • The pseudo-element behaves like a small visual layer that appears before the element’s content.

This approach works well when you want to add subtle decorative images to elements such as cards, buttons, or content blocks.

Creating a Full Overlay Background

One of the most common uses of the ::before pseudo-element is creating full overlay backgrounds.

.hero::before {

 content: “”;

 position: absolute;

 top: 0;

 left: 0;

 width: 100%;

 height: 100%;

 background-image: url(“hero.jpg”);

 background-size: cover;

 background-position: center;

 z-index: -1;

}

In this example, the pseudo-element acts like a background layer placed behind the content.

Here’s how the key properties work together:

  • position: absolute places the pseudo-element relative to its parent element.
  • width: 100% and height: 100% make the image cover the entire element.
  • background-size: cover ensures the image scales to fill the area without distortion.
  • background-position: center keeps the image centered.
  • z-index: -1 pushes the background behind the main content.

This technique is commonly used in hero sections, banners, and card layouts.

Why Developers Prefer This Method

Using background-image with the ::before pseudo-element provides much greater flexibility than inserting images directly with the content property.

It allows you to easily control important visual properties such as:

  • background-size – scale images using cover, contain, or custom values
  • background-position – control where the image appears inside the element
  • background-repeat – prevent images from repeating or create patterns
  • z-indexlayer images behind or in front of content

Because of this flexibility, this method is widely used in modern CSS layouts, UI components, and WordPress themes.

For example, developers often use it to:

  • create overlay effects in hero sections
  • add decorative shapes or textures to content blocks
  • build dynamic UI elements without modifying HTML

In WordPress environments, whether you’re styling Gutenberg blocks, Elementor widgets, or theme components, this technique allows you to enhance design purely through WordPress Custom CSS.

In short, combining background-image with the CSS ::before pseudo-element gives you a powerful way to add visual layers while keeping your HTML structure clean and maintainable.

Step-by-Step Guide: How to Set Image in ::before

Adding an image using the CSS ::beforepseudo-element is a simple technique that lets you insert visual elements before an HTML element’s content without adding extra markup.

Developers often use this approach to add icons, decorative graphics, or small UI accents while keeping the HTML clean and maintainable. The process typically involves creating the pseudo-element, inserting the image, and controlling its layout using CSS properties like position, width, height, and z-index.

Let’s walk through the workflow step by step.

Step 1: Select the HTML Element

First, choose the HTML element where the image should appear before the content.

For example:

<div class=”card”>

 Example content

</div>

Here, the <div> element with the class card will act as the target element. The image will appear before the text inside this element.

In CSS terms, this element becomes the base selector for attaching the ::before pseudo-element.

Step 2: Create the ::before Pseudo-Element

Next, create the pseudo-element using a CSS selector.

.card::before {

 content: “”;

}

The content property is required for the ::before pseudo-element to render. Even if you don’t want to insert text, you still need to define it with an empty string.

Think of this step as creating a virtual element that sits before the element’s content.

Step 3: Add the Image

Once the pseudo-element exists, you can attach an image to it using the background-image property.

.card::before {

 content: “”;

 background-image: url(“image.png”);

}

At this point, the image is technically applied, but it may not appear correctly yet. That’s because pseudo-elements do not automatically have dimensions or positioning.

So the next step is to define their layout.

Step 4: Set Size and Position

To make the image visible and properly placed, define its size and positioning.

.card::before {

 content: “”;

 background-image: url(“image.png”);

 width: 50px;

 height: 50px;

 position: absolute;

}

These properties control how the pseudo-element behaves in the layout:

  • width and height give the pseudo-element visible dimensions
  • position: absolute allows precise placement relative to the parent element
  • When using absolute positioning, the parent element often needs position: relative

Example:

.card {

 position: relative;

}

This ensures the pseudo-element is positioned within the card instead of the entire page.

Step 5: Adjust Layering with z-index

Finally, you may need to control how the image layers interact with other elements.

.card::before {

 z-index: 1;

}

The z-index property determines whether the pseudo-element appears:

  • above the content
  • behind the content
  • or between other elements

This is particularly useful when creating overlays, badges, or decorative graphics.

Real-World CSS ::before Image Examples

Understanding the CSS ::before pseudo-element becomes much easier when you see how it’s used in real projects. In everyday web development, designers often rely on this technique to add visual elements, like icons, overlays, or decorative shapes, without modifying the underlying HTML structure.

Because the ::before pseudo-element works through CSS selectors and the content property, it allows developers to enhance layouts while keeping the markup clean and maintainable.

Let’s look at a few practical examples where this technique is especially useful.

1. Adding Icons Before Menu Items

One of the most common uses of the ::before pseudo-element is adding small icons before navigation links or list items. Instead of inserting extra <img> elements in your HTML, you can generate the icon directly with CSS.

.menu li::before {

 content: url(“arrow.svg”);

 margin-right: 6px;

}

Here’s what happens in this example:

  • The CSS selector .menu li::before targets each list item in the navigation menu.
  • The content property inserts the image before the list text.
  • margin-right creates space between the icon and the text.

This approach is commonly used for:

  • Navigation menus
  • Feature lists
  • Checklist-style content
  • Blog article bullet icons

Pro Tip:
If you need more control over size and positioning, consider using a background-image with defined width, height, and CSS positioning instead of content: url().

2. Creating Image Overlays

Another powerful use case is building image overlays. By combining the ::before pseudo-element with absolute positioning, you can place graphics, gradients, or textures on top of existing elements.

.image-wrapper::before {

 content: “”;

 background-image: url(“overlay.png”);

 position: absolute;

 width: 100%;

 height: 100%;

}

In this scenario:

  • The pseudo-element creates a virtual layer before the content.
  • The background-image property adds the overlay graphic.
  • position: absolute allows the overlay to sit on top of the parent element.
  • The dimensions ensure the overlay covers the entire container.

This technique is frequently used in:

  • Hero section backgrounds
  • Banner overlays
  • Image cards
  • Portfolio thumbnails

To refine layering, developers often combine this setup with z-index so the overlay sits behind or above text, depending on the design.

3. Adding Decorative UI Elements

Sometimes you just want to add subtle visual details, like badges, shapes, or borders, without cluttering your HTML.

This is where the ::before pseudo-element shines.

Developers often use it to generate decorative elements such as:

  • notification badges
  • corner ribbons
  • background shapes
  • stylized borders
  • hover highlights

Because the pseudo-element is controlled entirely through CSS, these effects can be added, removed, or animated without touching the HTML elements themselves.

This technique works especially well in WordPress themes, where designers often enhance components inside Elementor widgets, Gutenberg blocks, or custom theme stylesheets using WordPress Custom CSS.

The result? Cleaner HTML, more flexible styling, and a UI that feels polished without adding extra markup.

Positioning and Styling Images in ::before

Because ::before behaves like a generated element, positioning matters.

Common Positioning Techniques

Absolute Positioning

.parent {

  position: relative;

}

.parent::before {

  position: absolute;

}

This anchors the pseudo-element relative to the parent.

Aligning Images with Text

You can use:

  • vertical-align
  • margin
  • padding

Example:

.item::before {

  content: url(“icon.svg”);

  margin-right: 10px;

  vertical-align: middle;

}

Managing Layering with z-index

Pseudo-elements often overlap with content.

Example:

.box::before {

  z-index: -1;

}

This moves the image behind the content.

Common Problems When Images Don’t Show

When working with the CSS ::before pseudo-element, it’s common to run into situations where your image simply doesn’t appear. This usually happens because one small but important CSS rule is missing.

If your image isn’t showing, check the following common issues before assuming something is broken.

1. Missing content Property

The content property is essential when using the ::before pseudo-element. Without it, the pseudo-element is never generated, which means your image, background, or styling won’t render at all.

Even if you plan to use a background-image, the pseudo-element still needs content.

Example:

.element::before {

 content: “”;

 background-image: url(“image.png”);

}

Here’s what happens:

  • content: “” creates the pseudo-element
  • background-image applies the image
  • The element now becomes visible and can be styled

Pro tip: Many developers forget this step when first learning pseudo-elements.

2. No Width or Height Defined

Another common issue occurs when the pseudo-element has no dimensions.

Unlike normal HTML elements, the ::before pseudo-element does not automatically take up space unless you explicitly define it.

If you’re using a background-image, make sure to define the element’s size.

Example:

.element::before {

 content: “”;

 background-image: url(“icon.png”);

 width: 40px;

 height: 40px;

 display: inline-block;

}

Without width and height, the pseudo-element may exist but remain invisible.

3. Parent Element Not Positioned Correctly

When you use CSS positioning such as position: absolute, the pseudo-element is positioned relative to its nearest positioned ancestor.

If the parent HTML element doesn’t have a positioning rule, the pseudo-element might appear in an unexpected location.

Correct setup:

.parent {

 position: relative;

}

.parent::before {

 content: “”;

 position: absolute;

 background-image: url(“image.png”);

}

This ensures the pseudo-element is positioned relative to the parent container instead of the page layout.

4. z-index Layering Issues

Sometimes the image exists, but it’s hidden behind another element because of z-index stacking order.

The z-index property controls which layers appear above others in a CSS layout.

For example:

.element::before {

 content: “”;

 background-image: url(“overlay.png”);

 position: absolute;

 z-index: 1;

}

If another element has a higher z-index, the image may be covered.

To fix this, adjust the stacking order so the pseudo-element appears in front or behind the correct layer.

Quick Troubleshooting Checklist

If your ::before image isn’t showing, quickly verify these four things:

  • The content property is defined
  • The pseudo-element has width and height
  • The parent element uses proper CSS positioning
  • The z-index stacking order is correct

In most cases, fixing one of these issues will immediately make the image appear.

Once these basics are handled, you can confidently use the CSS ::before pseudo-element to add icons, decorative graphics, and overlays without adding extra HTML elements.

Using CSS ::before Images in WordPress

If you’re working with WordPress, adding images with the CSS ::before pseudo-element is surprisingly easy. Since WordPress allows custom CSS in several areas, you can insert decorative icons, UI indicators, or background graphics without modifying your HTML elements.

This approach is especially useful when customizing WordPress themes, styling blocks, or adding visual cues to navigation items, buttons, and content sections.

Let’s look at the most common places where you can apply ::before styling in WordPress.

1. Using the WordPress Customizer (Additional CSS)

The simplest way to add custom CSS in WordPress is through the Customizer. This option is available in most modern WordPress themes and lets you apply styles globally without editing theme files.

Navigate to:

Appearance → Customize → Additional CSS

Here you can write CSS that targets specific HTML elements or CSS selectors.

Example:

.menu-item::before {

 content: url(“icon.svg”);

 margin-right: 8px;

}

This code inserts an icon before each menu item using the CSS content property and the ::before pseudo-element.

Why this method works well:

  • No need to edit theme files
  • Changes apply instantly
  • Safe for beginners

2. Adding Images with ::before in Elementor Custom CSS

If you’re using Elementor, especially Elementor Pro, you can apply custom CSS directly to widgets or sections. This makes it easy to add decorative icons or visual elements without touching your theme’s stylesheet.

Open the widget settings and add CSS like this:

selector::before {

 content: url(“icon.svg”);

 margin-right: 6px;

}

In Elementor, the keyword selector automatically targets the current widget.

This technique is often used to:

  • Add icons before headings
  • Style buttons with decorative elements
  • Insert small UI graphics without extra HTML markup

Because Elementor already handles layout and CSS positioning, pseudo-elements like ::before integrate very smoothly.

3. Styling Gutenberg Blocks with the ::before Pseudo-Element

If you use the Gutenberg block editor, you can apply pseudo-element styling by assigning a custom CSS class to a block.

Steps:

  1. Select the block in Gutenberg
  2. Open Advanced Settings
  3. Add a custom class name

Example class:

custom-block

Then add the CSS to your theme stylesheet or WordPress Customizer:

.custom-block::before {

 content: url(“icon.png”);

 margin-right: 10px;

}

This method works well for:

  • Feature lists
  • content highlights
  • visual markers before headings

Because the CSS selector targets the block, the pseudo-element appears automatically whenever that class is used.

4. Editing Theme CSS or Child Theme Stylesheets

For developers who prefer more control, you can place pseudo-element styles directly in your theme’s stylesheet.

Most themes store CSS rules inside:

style.css

However, it’s generally recommended to use a child theme stylesheet instead. This prevents your custom CSS from being overwritten during theme updates.

Example:

.feature-title::before {

 content: “”;

 background-image: url(“icon.png”);

 width: 20px;

 height: 20px;

 display: inline-block;

}

Using background-image instead of content: url() gives you more flexibility with:

  • image sizing
  • CSS positioning
  • z-index layering
  • background scaling

This approach is especially helpful when designing custom WordPress layouts or UI components.

Advanced Use Case: Image Overlays and Comparisons

The CSS ::before pseudo-element is often used to create visual overlays on images or UI elements. By combining the content property with a background-image, developers can layer decorative graphics or shading effects on top of existing HTML elements without adding extra markup.

For example, you might use ::before to add a semi-transparent overlay on a hero banner, highlight an image card, or display a decorative pattern behind content. Because the pseudo-element behaves like a generated layer, you can control it using CSS positioning and z-index, placing it above or below the main content.

Here’s a simple overlay example:

.image-wrapper {

 position: relative;

}

.image-wrapper::before {

 content: “”;

 position: absolute;

 inset: 0;

 background-image: url(“overlay-texture.png”);

 opacity: 0.4;

 z-index: 1;

}

In this example:

  • content: “” creates the pseudo-element
  • position: absolute allows the overlay to cover the element
  • background-image adds the visual layer
  • z-index controls how the overlay stacks with other elements

This technique works well for decorative effects, subtle textures, or visual highlights.

However, things get more complex when you want to compare two images interactively. A static overlay created with CSS can show a layered effect, but it doesn’t allow users to actively explore the difference between images.

That’s why many WordPress sites use before–after image comparisons to demonstrate changes such as:

While you could attempt this with advanced CSS positioning and JavaScript, it quickly becomes difficult to maintain.

In practice, many developers choose a Before After Image Slider plugin in WordPress to handle this functionality. These tools provide an interactive slider that lets users drag between two images while still allowing developers to style surrounding elements with CSS,  including overlays created with the ::beforepseudo-element.

This combination keeps the layout flexible while enabling richer visual storytelling on modern websites.

Best Practices for Using Images in CSS Pseudo-Elements

Using images inside the CSS ::before pseudo-element can be a powerful way to enhance visual design without adding extra HTML elements. However, like many CSS techniques, it works best when used thoughtfully.

Below are some practical best practices that help keep your layouts clean, maintainable, and performant, especially when working on modern websites or styling elements inside WordPress themes, Elementor widgets, or Gutenberg blocks.

Use Pseudo-Elements for Decorative Content

The ::before pseudo-element is best suited for decorative visuals rather than essential content.

Because it’s generated with CSS and not part of the actual HTML structure, screen readers and accessibility tools may ignore it. That means important images, such as product photos or informational graphics, should always be added using proper HTML elements like <img>.

Instead, use pseudo-elements for visual enhancements such as:

  • Small icons before text links or menu items
  • Decorative shapes or badges
  • Subtle background accents created with background-image
  • UI indicators like arrows, checkmarks, or separators

This keeps your HTML clean while still allowing creative design.

Optimize Images for Faster Performance

Images added with background-image or the CSS content property still affect page performance. Large files can slow down rendering, especially if multiple pseudo-elements are used on a page.

To keep things fast and efficient, use optimized image formats such as:

  • SVG: ideal for icons and vector graphics
  • WebP: excellent compression with high visual quality
  • Compressed PNG: useful for transparent graphics

These formats ensure decorative images load quickly across devices, which is especially important for responsive WordPress layouts and mobile users.

Keep Your CSS Clean and Maintainable

When working with pseudo-elements, clear CSS organization makes a big difference, especially in large projects or WordPress themes.

Follow simple practices like:

  • Use descriptive CSS selectors
  • Avoid deeply nested selectors
  • Keep styles grouped logically
  • Use consistent naming conventions for classes

For example:

.feature-icon::before {

 content: url(“check.svg”);

 margin-right: 8px;

}

Clean CSS improves readability and makes future updates easier for developers who may work on the project later.

Avoid Overusing Pseudo-Elements

While the ::before pseudo-element is flexible, using too many decorative layers can create unnecessary complexity.

Too many pseudo-elements may:

  • increase CSS complexity
  • create layout conflicts with CSS positioning or z-index
  • make debugging harder
  • slightly impacts rendering performance

A good rule of thumb is to use pseudo-elements only when they simplify markup or improve visual design.

If the layout becomes too complex, consider using regular HTML elements or structured CSS layouts instead.

Conclusion

Learning how to set images using the CSS ::before pseudo-element opens up a surprising number of creative possibilities.

With just a few lines of CSS, you can:

  • add icons before text
  • create decorative overlays
  • enhance UI elements
  • style components without extra HTML

The key is understanding when to use content: url() and when background-image offers more flexibility.

Once you master these techniques, you’ll start noticing opportunities to simplify your markup and create cleaner, more maintainable designs, whether you’re building custom websites or styling components inside WordPress.

And like many CSS techniques, the best way to learn is simple:

Experiment, tweak the code, and see what creative ideas you can bring to life.

Frequently Asked Questions (FAQs)

Can you insert an image using CSS ::before?

Yes. You can add images using the content: url() property or by applying a background-image to the ::before pseudo-element.

Why is my ::before image not showing?

The most common reasons are missing content, no width or height, or incorrect positioning. Always ensure the pseudo-element is properly defined.

Can ::before be used on <img> elements?

No. Pseudo-elements cannot be applied to replaced elements such as <img>, <video>, or <iframe>.

How do you resize an image in a pseudo-element?

If you use content: url(), resizing is limited. For better control, use background-image with background-size.

Can CSS pseudo-element images have alt text?

CSS-generated images usually don’t support traditional alt text. For accessible content, use an HTML <img> element instead.

This page was last edited on 11 March 2026, at 3:40 pm