CSS - Pseudo Classes



Pseudo-classes in CSS are used to select and style elements based on their state or position within the document tree, without the need for adding extra classes or IDs to the HTML elements. These pseudo-classes are primarily used for creating interactive and dynamic styles in web pages.

Syntax

selector:pseudo-class {
   property: value;
}
  • Pseudo-classes start with a colon (:) and follow a selector. For example: :hover, :focus, etc.

  • A functional pseudo-class contains a pair of parentheses to define the arguments. For example: :lang().

  • The element to which a pseudo-class is attached, is termed as an anchor element. For example: button:hover, a:focus, etc. Here button and a elements are called the anchor elements.

  • Pseudo-classes apply style to an element as per the content of the document tree.

  • Pseudo-classes also apply a style to an element in relation to the external factors, such as history of the navigation of the element (:visited), status of the content (:checked), or position of mouse (:hover)

Unlike pseudo-classes that style the entire element, pseudo-elements target and style a specific part of an element.

Just like the regular classes, you have the flexibility to combine multiple pseudo-classes within a single selector.

Element Display State Pseudo-classes

The pseudo-classes such as :fullscreen, :modal and :picture-in-picture are the pseudo-classes that targets and styles elements based on their display state.

Here is an example of :fullscreen pseudo-class:

<html>
<head>
<style>
   .sample {
      padding: 10px;
      height: 200px;
      width: 95%;
      background-color: lightgrey;
   }
   .sample p {
      visibility: hidden;
      text-align: center;
      color: black;
      font-size: 2em;
   }
   .sample:fullscreen {
      background-color: lightsalmon;
      width: 100vw;
      height: 100vh;
   }
   .sample:fullscreen p {
      visibility: visible;
   }
</style>
</head>
<body>
   <h2>:fullscreen example</h2>
   <div class="container"> 
      <div class="sample" id="sample">
      <p>Fullscreen mode</p>
      </div>
      <br>
      <button onclick="var el=document.getElementById('sample'); el.webkitRequestFullscreen();">Click here</button>
   </div>
</body>
</html>

Here is an example of :modal pseudo-class:

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

   :modal {
      border: 8px inset blue;
      background-color: lightpink;
      box-shadow: 3px 3px 10px rgba(0 0 0 / 0.5);
   }
</style>
</head>
<body>
   <dialog>
      <button autofocus>Close</button>
      <p>The modal dialog has a beautiful backdrop!</p>
      <p>And see my styling using :modal pseudo-class</p>
   </dialog>
   <button>Open the dialog</button>

   <script>
      const dialog = document.querySelector("dialog");
      const showButton = document.querySelector("dialog + button");
      const closeButton = document.querySelector("dialog button");

      // "Show the dialog" button opens the dialog modally
      showButton.addEventListener("click", () => {
      dialog.showModal();
      });

      // "Close" button closes the dialog
      closeButton.addEventListener("click", () => {
      dialog.close();
      });
   </script>
</body>
</html>

Input Pseudo-classes

The pseudo-classes that targets and styles the <input> elements, and enables the selection of elements based on the HTML attributes, along with the state in which the element is before and after user interaction, are shown with examples in following section.

Here is an example of :autofill pseudo-class:

<html>
<head>
<style>
   label {
      display: block;
      margin-top: 1em;
   }
   input {
      border: 3px solid grey;
      border-radius: 3px;
   }

   input:-webkit-autofill {
      border: 3px solid green;
      background-color: yellow;
   }

   input:autofill {
      border: 3px solid green;
      background-color: yellow;
   }
</style>
</head>
<body>
   <h3>:autofill example</h3>
   <form method="post" action="">
      <label for="name">First Name</label>
      <input type="first-name" id="name" />
      <label for="name">Last Name</label>
      <input type="last-name" id="name" />
      <label for="email">Email</label>
      <input type="email" name="email" id="email" autocomplete="email" />
   </form>
</body>
</html>

Here is an example of :enabled pseudo-class:

<html>
<head>
<style>
	input[type=text]:enabled {
		background: white;
	}

	input[type=text]:disabled {
		background: lightgrey;
	}

	input {
		width: 150px;
		padding-left: 10px;
		margin-top: 10px;
		border: 1px solid black;
	}

   form {
      border: 2px solid black;
      width: 300px;
      padding: 10px;
   }
</style>
</head>
<body>
	<h2>:enabled example</h2>
	<form action="">
      <label>First Name</label>
      <input type="text"><br>
      <label>Last Name</label>
      <input type="text"><br>
      <label>Address</label>
      <input type="text" disabled="disabled" value="Address"><br><br>
      <button type="submit" disabled="disabled">Submit</button>
      <button type="reset">Reset</button>
	</form>
</body>
</html>

Here is an example of :disabled pseudo-class:

<html>
<head>
<style>
	input[type=text]:enabled {
		background: white;
	}

	input[type=text]:disabled {
		background: lightgrey;
	}

	input {
		width: 150px;
		padding-left: 10px;
		margin-top: 10px;
		border: 1px solid black;
	}
</style>
</head>
<body>
	<h2>:disabled example</h2>
	<form action="">
      <label>Doctor Name</label>
      <input type="text"><br>
      <label>Hospital Name</label>
      <input type="text"><br>
      <label>Diagnosis</label>
      <input type="text" disabled="disabled" value="Diagnosis"><br><br>
      <button type="submit" disabled="disabled">Submit</button>
      <button type="reset">Reset</button>
	</form>
</body>
</html>

Other such pseudo-classes are ::read-only, :read-write, :placeholder-shown, :default, :checked, :indeterminate, :blank, :valid, :invalid, :in-range, :out-of-range, :required, :optional, and :user-invalid.

Linguistic Pseudo-classes

The pseudo-classes that reflects the language of the document and enables the selection of elements according to the direction of language or script, falls under this category.

Here is an example of :lang() pseudo-class:

<html>
<head>
<style>
   :lang(en) > q {
      quotes: '""';
   }
   :lang(fr) > q {
      quotes: '« ' ' »';
      color: white;
      background-color: steelblue;
   }
   div {
      padding: 10px;
   }
</style>
</head>
<body>
   <h2>:lang() selector example</h2>
   <div lang="en">
   <q>Lorem ipsum is simply dummy text</q>
   </div>
   <div lang="fr">
   <q>Lorem ipsum is simply dummy text</q>
   </div>
</body>
</html>

Location Pseudo-classes

The pseudo-classes that relate to links and to the targeted elements within the same current document, comes under this category of pseudo-classes.

These are :any-link, :link, :visited, :target, and :scope. Few examples are shown below.

Here is an example of changing the foreground & background color of a link using :any-link:

<html>
<head>
<style>
   div {
      padding: 5px;
      border: 2px solid black;
      margin: 1em;
      width: 500px;
   }

   a:any-link {
      font-weight: 900;
      text-decoration: none;
      color: green;
      font-size: 1em;
   }

   .with-nohref {
      color: royalblue;
   }

   .with-empty {
      color: crimson;
   }
</style>
</head>
<body>
   <h3>:any-link example</h3>
   <div>
      anchor elements with href to tutorialspoint.com--
      <a href="https://tutorialspoint.com">click here</a>
   </div>
   <div>
      <a class="with-nohref">with no href</a>
   </div>
   <div>
      <a href="#" class="with-empty">with empty href</a>
   </div>
</body>
</html>

Here is an example of :link pseudo-class, along with :hover pseudo-class:

<html>
<head>
<style>
   a {
      font-size: 1em;
      padding: 5px;
      display: inline-block;
      margin-right: 10px;
   }

   a:link {
      background-color: lightyellow;
   }

   a:hover {
      background-color: lightsalmon;
      color: green;
   }
</style>
</head>
<body>
   <h2>:link selector example</h2>
   <strong><a href="https://www.tutorialspoint.com">Tutorialspoint</a></strong>
   <strong><a href="https://www.google.com">Google</a></strong>
</body>
</html>

Tree Structural Pseudo-classes

The pseudo-classes that target the elements based on the location of the element within the document tree, comes under this category of pseudo-classes.

They are :root, :empty, :nth-child, :nth-last-child, :first-child, :last-child, :only-child, :nth-of-type, :nth-last-of-type, :first-of-type, :last-of-type and :only-of-type. Few examples are shown below.

Here is an example of :empty pseudo-class, applied on <p> tag:

<html>
<head>
<style>
   p:empty {
      width: 200px;
      height: 30px;
      background: magenta;
   }
   div {
      border: 3px solid black;
      width: 300px;
      text-align: center;
   }
</style>
</head>
<body>
   <h2>:empty example</h2>
   <div>
   <p>Not an empty paragraph</p>
   <p></p>
   <p>Not an empty paragraph</p>
   </div>
</body>
</html>

Here is an example of :first-child pseudo-class, applied on <p> tag, under <div> parent element. In this example, the CSS rules will only apply to the first <p> element found within a <div> element, leaving other <p> elements within the same container unaffected.

<html>
<head>
<style>
   p:first-child {
      color: black;
      background: yellow;
      font-weight: 600;
      font-size: 1em;
      font-style: italic;
      padding: 5px;
   }
   div {
      border: 2px solid black;
      margin-bottom: 5px;
   }
</style>
</head>
<body>
   <div>Parent element
      <p>first child looks different due to :first-child pseudo-class</p>
      <p>second child, so no change</p>
   </div>
   <div>Parent element
      <h2>h3 tag, so no change</h2>
      <p><p> tag, but not the first child.</p>
   </div>
</body>
</html>

Here is an example of :only-of-type pseudo-class, applied on <p> and <h2> tags, under <div> parent element. In this example, the CSS rules will only apply to the <p> and <h2> type elements found in the <div> parent container.

<html>
<head>
<style>
   .field {
      margin: 1px;
      padding: 1px;
   }

   p:only-of-type {
      color: darkblue;
      background-color: lightpink;
      padding: 5px;
   }

   h2:only-of-type {
      text-decoration-line: underline;
      color: green;
   }

   div {
      border: 2px solid black;
      width: 500px;
   }
</style>
</head>
<body>
   <div class="field">
      <h2>Heading 2 - only type</h2>
      <p>Paragraph tag - only type</p>
   </div>
   
   <div class="field">
      <h2>Heading 2 - only type</h2>
      <p>Paragraph tag 1 - we are two</p>
      <p>Paragraph tag 2 - we are two</p>
   </div>
</body>
</html>

User Action Pseudo-classes

All these pseudo-classes need some user interaction or intervention in order for them to apply the rule or styling, such as clicking on an input field, or hovering over a button, etc.

These pseudo-classes are :active, :focus, :focus-visible, :focus-within, and :hover. Few examples are shown below.

Here is an example where focus is set on a link:

<html>
<head>
<style>
    a {
        color: darkviolet;
        transition: all 0.3s ease;
    }

    a:focus {
        outline: none;
        color: red;
        background-color: yellow;
    }

    body {
        margin: 5px;
        padding: 2rem;
        display: grid;
        font: 20px/1.4 system-ui, -apple-system, sans-serif;
    }
</style>
</head>
<body>
    <p>The link here has a <a href="#0">change in background and foreground color</a> as it is focussed.</p>
</body>
</html>

Here is an example where focus is set on an input field, sets the focus on its label, using :focus-within:

<html>
<head>
<style>
      label {
         display: block;
         font-size: 20px;
         color: black;
         width: 500px;
      }

      input[type="text"] {
         padding: 10px 16px;
         font-size: 16px;
         color: black;
         background-color: #fff;
         border: 1px solid #597183;
         border-radius: 8px;
         margin-top: 5px;
         width: 500px;
         transition: all 0.3s ease;
      }

      input[type="text"]:focus {
         background-color: lightyellow;
      }

      label:focus-within {
         font-size: 25px;
         color: red;
      }
</style>
</head>
<body>
      <form>
         <label>
         Full Name
         <input type="text">
         </label>
      </form>
</body>
</html>

Here is an example of changing the border, foreground & background color of a button, using :active pseudo-class:

<html>
<head>
<style>
   div {
      padding: 1rem;
   }
   button {
      background-color: greenyellow;
      font-size: large;
   }
   button:active {
      background-color: gold;
      color: red;
      border: 5px inset grey;
   }
</style>
</head>
<body>
      <h3>:active example - button</h3>
      </div>   
         <button>Click on me!!!</button>
      </div>
</body>
</html>

Functional Pseudo-classes

The listed pseudo-classes acts as a function and accepts a selector list or forgiving selector list as argument. They are :is(), :has(), :not(), and :where().

Here is an example of :is() function pseudo-class, where :is pseudo-class is applied on the elements like h1, h2, h3 and a. So wherever these elements are found, the appropriate styles are applied:

<html>
<head>
<style>
   body {
      font: 300 90%/1.4 system-ui;
      margin: 1rem;
   }
   main :is(h1, h2, h3) {
      color: green;
   }
   main :is(a) {
      color: red;
      font-size: large;
   }
</style>
</head>
<body>
   <main>
      <h1>:is() pseudo-class example</h1>
      <h3>Li Europan lingues</h3>
      <a href="">es membres del sam familie</a>. <p>Lor separat existentie es un myth.</p>
      <h2>Por scientie, musica, sport etc, litot Europa usa li sam vocabular.</h2>
      <p>Li lingues differe solmen in li grammatica, li pronunciation e li plu commun vocabules. Omnicos directe al desirabilite de un nov lingua franca: On refusa continuar payar custosi traductores.</p>
      <p>At solmen va esser necessi far uniform grammatica, pronunciation e plu sommun paroles.</p>
      <h3>Ma quande lingues coalesce</h3>
      <p>li grammatica del resultant lingue es plu simplic e regulari quam ti del coalescent lingues. Li nov lingua franca va esser plu simplic e regulari quam li existent Europan lingues.</p>
      <p>It va esser tam simplic quam <a href="">Occidental</a> in fact, it va esser Occidental.</p>
   </main>
</body>
</html>

Here is an example of :not() pseudo-class, where the styling defined using the .sample class is not applied on h1 element due to :not(h1):

<html>
<head>
<style>
   .sample {
      text-shadow: 2px 2px 3px yellow;
   }

   /* <h1> elements that are not in the class '.sample' */
   h1:not(.sample) {
      background-color: lightblue ;
   }

   /* Elements that are not <h1> elements */ 
   body :not(h1) {
      text-decoration-line: line-through;
   }

   /* Elements that are not <div> and not <span> elements */
   body :not(div):not(span) {
      font-weight: bold;
   }
</style>
</head>
<body>
   <h1>heading with :not(.sample) pseudo-class applied</h1>
   <h1 class="sample">heading with styling applied</p>
   <p>Paragraph, hence :not(h1) and :not(div):not(span) applied.</p>
   <div>div element, hence :not(h1) applied.</div>
</body>
</html>

The table given below lists all the CSS pseudo-classes:

Pseudo-class Description Example
:active Represents an element that has been activated by the user. a:active{}
:any-link Represents an element that acts as the source anchor of a hyperlink, independent of whether it has been visited. a:any-link{}
:autofill Matches an element that has its value autofilled by the browser. input:autofill{}
:checked Matches any radio, checkbox or option element that is checked or toggled. input:checked{}
:default Selects form elements that are the default in a group of related elements. input:default{}
:defined Represents any element that has been defined. <custom-element>:defined{}
:disabled Represents a disabled element. input:disabled{}
:empty Matches an element that has no children. div:empty{}
:enabled Represents an enabled element, after its has been activated. input:enabled{}
:first Represents the first page of a printed document, with the @page at-rule. @page:first{}
:first-child Represents the first element among a group of sibling elements. li:first-child{}
:first-of-type Represents the first element of its type among a group of sibling elements. p:first-of-type{}
:fullscreen Matches an element that is currently displayed in fullscreen mode. #id:fullscreen{}
:focus Represents an element that has received focus. input:focus{}
:focus-visible Applies while an element matches the :focus pseudo-class or receives focus. input:focus-visible{}
:focus-within Matches an element if the element or any of its descendants are focused. label:focus-within{}
:has() This represents an element if any of the relative selectors. :has()
:host This selects the shadow host of the shadow DOM containing the CSS it is used inside. :host{}
:host() This function selects the shadow host of the shadow DOM containing the CSS it is used inside. :host()
:host-context() This function allows you to style a custom element based on the classes or attributes of its ancestor elements. :host-context()
:hover Matches when the user interacts with an element with a pointing device, like a mouse, but does not necessarily activate it. button:hover{}
:indeterminate Represents any form element whose state is indeterminate or unknown. input:indeterminate{}
:in-range Represents an element whose current value is within the range limits. input:in-range{}
:invalid Represents any element whose contents fail to validate. input:invalid{}
:is() Takes a selector list as its argument, and selects any element that can be selected by one of the selectors in that list. :is(ol, ul){}
:lang() Matches an element based on the language they are defined to be in. *:lang(en){}
:last-child Represents the last element among a group of sibling elements. li:last-child{}
:last-of-type Represents the last element of its type among a group of sibling elements. p:last-of-type{}
:left Represents all left-hand pages of a printed document, used with @page at-rule. @page:left{}
:link Represents an element that has not yet been visited. a:link{}
:modal Matches an element that is in a state in which it excludes all interaction with elements outside it until the interaction has been dismissed. :modal{}
:not() Represents an element that do not match a list of selectors. p:not(strong){}
:nth-child() Selects child elements according to their position among all the sibling elements within a parent element. li:nth-child(-n+3){}
:nth-last-child() Matches elements based on their position among siblings, counting from the last (end) li:nth-last-child(odd){}
:nth-last-of-type() Matches elements based on their position among siblings of the same type, counting from the last (end). dd:nth-last-of-type(3n){}
:nth-of-type() Matches elements based on their position among siblings of the same type. dd:nth-of-type(even){}
:only-child Represents an element without any siblings. li:only-child{}
:only-of-type Represents an element that has no siblings of same type. a:only-of-type{}
:optional Represents an element that does not have a required attribute set on it. input:optional{}
:out-of-range Represents an element whose current value is outside the range limits. input:out-of-range{}
:picture-in-picture Matches an element that is currently in picture-in-picture mode. :picture-in-picture{}
:placeholder-shown Represents any element that is currently displaying placeholder text. input:placeholder-shown{}
:read-only Represents an element that is not editable by the user. textarea:read-only{}
:read-write Represents an element that is editable by the user. textarea:read-write{}
:required Represents an element that has a required attribute set on it. input:required{}
:right Represents all right-hand pages of a printed document, used with @page at-rule. @page:right{}
:root Matches the root element of a document tree. :root{}
:scope Represents elements that are a reference point, or scope, for selectors to match with. :scope{}
:target Represents the target element with an id matching the URL's fragment. p:target{}
:valid Represents any element whose contents validate successfully. input:valid{}
:visited Applies once the link has been visited. a:visited{}
:where() Takes a selector list as its argument and selects any element that matches. :where(ol, ul){}
Advertisements