Pseudo Elements

Pseudo elements are parts of an element that you can style independently. They do not require any additional markup to use. You place the keyword for the pseudo element you want after the selector for that element. The pseudo elements currently available are:

This page will focus on the pseudo elements ::before and ::after only.

::before and ::after

::before and ::after are pseudo elements that are contained by an element's formatting box.

::before allows you to add content with css that will be the first child of the element, and therefore it will appear before the element's content. ::after allows you to add content with css that will be the last child of the element, and therefore it will appear after the element's content.

::before and ::after are both inline by default.

                        
<div>
    <h1>Heading</h1>
    <p>Paragraph</p>
</div>
<style>
    div{
        background-color: #e4e4db;
        color: #35353c
    }
    div::before{
        content: "div::before";
        background-color: #bbbbb4;
    }
    div::after{
        content: "div::after";
        background-color: #a6a6a0;
    }
    h1{
        background-color: #e4e4db;
    }
    h1:before{
        content: "h1::before";
        background-color: #bbbbb4;
    }
    h1::after{
        content: "h1::after";
        background-color: #a6a6a0;
    }
</style>
                        
                    

Heading

Paragraph

Stacking Order

The default stacking order of an element and it's ::before and ::after pseudo elements is for the child element ::before to display on top of the element and the child element ::after to stack on top of ::before.

                            
    h1::before{
        position: relative;
        left: 6.5em;
        top: .75em;
    }
    h1::after{
        position: relative;
        top: 1.5em;
    }
                            
                        

Heading

Paragraph

Because the pseudo elements are considered child elements, changing the z-index on them and the parent will not always work to stack them behind the parent element. First you must give the element a stacking context within its container element. Set position and z-index for the element that contains the parent. Do NOT set a z-index for the parent, but DO set z-index for the child pseudo elements.

                            
    div{
        position: relative;
        z-index: 0;
    }
    h1::before{
        z-index: -1;
        }
    h1::after{
        z-index: -2;
    }
                            
                        

Heading

Paragraph

Content

The CSS content property allows you to add content outside of the HTML, that will not appear in the DOM.

The initial value for elements is normal. For ::before and ::after pseudo elements, normal computes to none and the elements do not render at all.

The content property must be set to an empty string if you wish to use the pseudo element for its shape only. Other common values are a string of text, an image, a counter, or open and close quotes.

                            
<div>
    <h1>Content Values</h1>
    <ol>
        <li>empty string</li>
        <li>string</li>
        <li>image</li>
        <li>counter</li>
        <li>open and close quotes</li>
    </ol>
</div>
<style>
    div{
        padding: 10px;
        background-color: #e4e4db;
        color: #35353c
    }
    ol{
        list-style: none;
        counter-reset: li;
    }
    li{
        counter-increment: li;
    }
    ::before, ::after{
        background-color: #bbbbb4;
    }
    li:nth-of-type(1)::before{
        content: "";
        display: inline-block;
        width: 30px;
        height: 20px;
    }
    li:nth-of-type(2)::before{
        content: "This is the ::before content."
    }
    li:nth-of-type(3)::before{
        content: url(./images/arrow.png);
    }
    li:nth-of-type(4)::before{
        content: counter(li);
    }
    li:nth-of-type(5)::before{
        content: open-quote;
    }
    li:nth-of-type(5)::after{
        content: close-quote;
    }
</style>
                            
                        

Content Values

  1. empty string
  2. string
  3. image
  4. counter
  5. open and close quotes

Examples

Two examples that I used on this webpage are zigzag borders and wave borders. With ::before and ::after pseudo elements you can create complex, decorative borders like these with only one or two <div>s in the HTML.

                            
<div class="example"></div>
<div class="wave"></div>
<style>
    .example{
        position: absolute;
        right: 90px;
        height: 100%;
        width: 80px;
        background-color: #bbbbb4;
    }
    .example::before{
        content:"";
        display: block;
        position: absolute;
        height: 100%;
        width: 10px;
        background: 
            linear-gradient(-135deg, #bbbbb4 5px, transparent 0) 0 5px, 
            linear-gradient(320deg, #bbbbb4 5px, transparent 0) 0 5px;    
        background-position: left top;
        background-repeat: repeat-y;
        background-size: 10px 10px;
        left: -10px;
    }
    .wave{
        position: absolute;
        color: #bbbbb4;
        width: 150px;
        height: 100%;
        overflow: hidden;
        right: -60px;
    }
    .wave::before{
        content: "";
        display: block;
        position: absolute;
        width: 40px;
        height: 50.1%;
        background: #bbbbb4;
        border-radius: 0 100% 0 0;
    }
    .wave::after{
        content: "";
        display: block; 
        position: absolute;
        width: 40px;
        height: 50.1%;
        background: transparent;
        border-radius: 0 0 0 100%;
        border: solid #bbbbb4;
        border-width: 0 0 0 2000px;
        bottom: -0.5px;
        right: 70px;
    }
</style>
                            
                        

References