CSS - Pseudo Elements


A pseudo-element, in CSS, is a keyword that is used to style a specific part of an element. Pseudo-elements are not part of the DOM (Document Object Model) and do not exist in the HTML markup, but they can be targeted and styled using CSS.

Overview

  • Pseudo-elements are denoted by a double colon (::) notation. On the other hand the pseudo-classes use single colon (:).

  • Only one pseudo-element can be used in a selector.

  • A pseudo-element in a selector must appear after all the other components. For example, p::last-line:hover is invalid.

  • Pseudo-elements can be used to add decorative styles, create special effects, and modify the appearance of certain parts of an element, that has a state already applied to it. For example, p:hover::last-line is a valid statement and selects the last line of the paragraph when the paragraph is hovered

  • The pseudo-elements are often used in conjunction with the content property to add text or images.

The complete style gets ignored, when the selector list consists of an invalid selector.

Syntax

selector::pseudo-element {
   property: value;
}

The following table shows the most commonly used pseudo-elements in CSS:

Pseudo-element Description
::after Adds a pseudo-element that is the last child of the selected element.
::backdrop Adds a box beneath the selected element as per the size of the viewport.
::before Adds a pseudo-element that is the first child of the selected element.
::cue Used to style the captions and cues in media with video text tracks.
::first-letter Applies styles to the first letter of the first line of a block level element.
::first-line Applies styles to the first line of a block level element.
::file-selector-button Represents the button of an <input> of type="file".
::marker Selects the marker box of a list item.
::part() Represents an element within a shadow tree that has a matching part attribute.
::placeholder Represents a placeholder text in an <input> or <textarea> element.
::selection Applies styles to the selected part of the document (selected by clicking and dragging the mouse across text).
::slotted() Represents an element that has been placed into a slot inside an HTML template.

The single colon syntax is supported by the browsers for the four original pseudo-elements, i.e., ::before, ::after, ::first-line, and ::first-letter.

CSS ::after Pseudo-element

Following example demonstrates use of ::after pseudo-element:

<html>
<head>
<style>
   p:after {
      content: url(images/smiley.png)
   }
</style>
</head>
<body>
   <p> First line.</p>
   <p> Second line.</p>
   <p> Third line.</p>
</body>
</html>

CSS ::backdrop Pseudo-element

Following example demonstrates use of ::backdrop pseudo-element:

<html>
<head>
<style>
      dialog::backdrop {
         background-image: url("images/border.png");
      }

      * {
         box-sizing: border-box;
      }
      body {
         margin: 0;
         font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif;
         background-color: #3d3e3e;
         color: white;
      }
      .container {
         max-width: 100%;
         margin: 0 auto;
         padding: 2rem;
      }
      button {
         display: inline-block;
         border: 1px solid #007bff;
         padding: 5px;
         font-size: 1rem;
         color: black;
         background-color: #bfc2c5;
         cursor: pointer;
      }
      @supports not selector(::backdrop) {
         body::before {    
         box-sizing: border-box;
         content: '';
         }
      }
</style>
</head>
<body>
      <div class="container">
         <p>pseudo-element backdrop used to create a background</p>
         <button onclick="openDialog()">Click to Open dialog</button>
         <dialog>
            <p>See the backdrop</p>
            <button onclick="closeDialog()">Close</button>
         </dialog>  
      </div>
      <script>
         var dialog = document.querySelector('dialog');
         function openDialog() {  
         dialog.showModal();
         }
         function closeDialog() {  
         dialog.close();
         }
      </script>
</body>
</html>

CSS ::before Pseudo-element

Following example demonstrates use of ::before pseudo-element:

<html>
<head>
<style>
   p:before {
      content: url(images/smiley.png)
   }
</style>
</head>
<body>
   <p> First line.</p>
   <p> Second line.</p>
   <p> Third line.</p>
</body>
</html>

CSS ::cue Pseudo-element

Following example demonstrates use of ::cue pseudo-element:

<html>
<head>
<style>
    video {
        width: 800px;
    }

    video::cue {
        font-size: 1rem;
        color: peachpuff;
    }
</style>
</head>
<body>
    <video controls src="foo.mp4">
        <track default kind="captions" srclang="en" src="cue-sample.vtt" />
    </video>    
</body>
</html>

CSS ::first-letter Pseudo-element

Following example demonstrates use of ::first-letter pseudo-element:

<html>
<head>
<style>
   p::first-letter { 
      text-transform: lowercase;
      font-size: 2em;
      color: red;
   }
</style>
</head>
<body>
   <p>
      The first line of this paragraph will be underlined and the first letter is lowercase, 2em and red in color, as pseudo-element ::first-line & ::first-letter is applied on p.<br />
      The second line is not underlined.
   </p>
</body>
</html>

CSS ::first-line Pseudo-element

Following example demonstrates use of ::first-line pseudo-element:

<html>
<head>
<style>
   p::first-line { 
      text-transform: lowercase;
      font-size: 2em;
      color: red;
   }
</style>
</head>
<body>
   <p>
      The first line of this paragraph will be underlined and the first letter is lowercase, 2em and red in color, as pseudo-element ::first-line & ::first-letter is applied on p.<br />
      The second line is not underlined.
   </p>
</body>
</html>

CSS ::file-selector-button Pseudo-element

Following example demonstrates use of ::file-selector-button pseudo-element:

<html> 
<head>
<style>
    body {
        display: block;
        height: 100vh;
        margin: 0;
        }

    input::file-selector-button {
        background-image:url(images/border.png);
        background-size: 200%;
        border: 2px solid black;
        border-radius: 8px;
        font-weight: 600;
        color: rgb(6, 1, 9);
        padding: 15px;
        transition: all 0.25s;
    }
</style>
</head>
<body>
    <h2>Select a file</h2>
    <input type="file">
</body>
</html>

CSS ::marker Pseudo-element

Following example demonstrates use of ::marker pseudo-element:

<html> 
<head>
<style>
      ol li::marker {
         color: rgb(11, 38, 241);
         font-weight: bold;
      }
      ul li::marker {
         content: url('images/smiley.png')
      }
      body {
         line-height: 1.4;
         font-family: Verdana, Geneva, Tahoma, sans-serif;
      }
</style>
</head>
<body>
      <h2>Numbered list</h2>
      <ol>
         <li>One</li>
         <li>Two</li>
         <li>Three</li>
      </ol>
      <h2>Bulleted list</h2>
      <ul>
         <li>One</li>
         <li>Two</li>
         <li>Three</li>
      </ul>
</body>
</html>

CSS ::part() Pseudo-element

Following example demonstrates use of ::part() pseudo-element:

<html> 
<head>
<style>
   .container {
      max-width: 500px;
      margin: 0 auto;
      padding: 2em;
   }

   body {
      font: 1em/1.618 Segoe UI, sans-serif;
   }

   new-widget::part(widget) {
      max-width: 300px;
      padding: 1em;
      background-color: lightgoldenrodyellow;
      border-radius: 20%;
   }
</style>
</head>
<body>
   <div class="container">
      <p>This paragraph is rendered as normal without any style.</p>
      <template id="new-widget">
         <div part="widget">
         <p>This paragraph is rendered as a part of the main paragraph and thus the ::part() pseudo-element is applied here.</p>
         </div>
         </template>
      <new-widget></new-widget>
      <script>
         let template = document.querySelector("#new-widget");
         globalThis.customElements.define(
         template.id,
         class extends HTMLElement {
         constructor() {
         super()
         .attachShadow({ mode: "open" })
         .append(template.content);
         }
         }
         );
      </script>       
   </div>
</body>
</html>

CSS ::placeholder Pseudo-element

Following example demonstrates use of ::placeholder pseudo-element:

<html> 
<head>
<style>
   .form {
      border: 2px solid black;
      background: lightgray;
      margin: 15px;
      padding: 25px;
      width: 250px;
   }

   input::placeholder { 
      color: grey; 
      font-style: italic;
      background-color: cornsilk;
      padding: 5px;
   }

   input {
      margin-bottom: 3px;
   }
</style>
</head>
<body>
   <div class="form">
      <input type="text" placeholder="First Name">
      <input type="text" placeholder="Last Name">
      <input type="text" placeholder="Address">
      <input type="text" placeholder="Phone">
   </div>
</body>
</html>

CSS ::selection Pseudo-element

Following example demonstrates use of ::selection pseudo-element:

<html> 
<head>
<style>
   .highlight::selection { 
      color: yellow;
      background: brown;
   } 
</style>
</head>
<body>
   <p class="highlight">Select Me!!! to see the effect.</p>
   <p>No style applied to me.</p>
</body>
</html>

CSS ::slotted() Pseudo-element

Following example demonstrates use of ::slotted() pseudo-element:

<html>
<head>
</head>
<body>
   <template id="sample-template">
      <style>
         ::slotted(.p-text) {
            background-color: lavender;
         }

         h2::slotted(.heading) {
            background: silver;
         }

         ::slotted(#footer-text) {
            background-color: lightsteelblue;
            border: 2px solid black;
         }
      </style>
      <div>
         <h2><slot name="heading">title goes here</slot></h2>
         <slot name="p-text">content goes here</slot>
         <slot name="footer-text">Footer here</slot>
      </div>
   </template>

   <sample-card>
      <span class="heading" slot="heading">::Slotted Example</span>
      <p class="p-text" slot="p-text">Paragraph text</p>
      <p id="footer-text" slot="footer-text">Footer text</p>
   </sample-card>

   <script>
      customElements.define(
         'sample-card',
         class extends HTMLElement {
         constructor() {
         super();

         const template = document.getElementById('sample-template');
         const shadow = this.attachShadow({ mode: 'open' });
         shadow.appendChild(template.content.cloneNode(true));

         const elementStyle = document.createElement('style');
         elementStyle.textContent = `
         div {
         width: 250px;
         border: 5px inset green;
         border-radius: 2px;
         padding: 5px;
         }`;
         shadow.appendChild(elementStyle);

         const cssTab = document.querySelector('#css-output');
         const editorStyle = document.createElement('style');
         editorStyle.textContent = cssTab.textContent;
         shadow.appendChild(editorStyle);
         cssTab.addEventListener('change', () => {
         editorStyle.textContent = cssTab.textContent;
         });
         }
      },
      );
   </script>
</body>
</html>

Multiple Pseudo-elements

Following example demonstartes usage of multiple pseudo-elements (::first-line and ::first-letter).

<html>
<head>
<style>
   p::first-line { text-decoration: underline; }
   p::first-letter { 
      text-transform: lowercase;
      font-size: 2em;
      color: red;
   }
</style>
</head>
<body>
   <p>
      The first line of this paragraph will be underlined and the first letter is lowercase, 2em and red in color, as pseudo-element ::first-line & ::first-letter is applied on p.<br />
      The second line is not underlined.
   </p>
</body>
</html>
Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements