CSS Pseudo-elements ๐ŸŽฏ

Style specific parts of elements and create decorative content without extra HTML markup.

What are CSS Pseudo-elements?

Pseudo-elements are CSS keywords that let you style specific parts of an element. They allow you to create virtual elements that Don't exist in the HTML DOM but can be styled and positioned as if they were real elements.

๐ŸŽจ Decorative Content

Add icons, shapes, and decorations without HTML

โšก No Extra Markup

Keep HTML clean and semantic

๐Ÿ”ง Powerful Styling

Style specific text parts and generated content

Basic Pseudo-elements

Key Pseudo-elements:

  • ::before - Inserts content before an element
  • ::after - Inserts content after an element
  • ::first-letter - Styles the first letter of text
  • ::first-line - Styles the first line of text
  • ::selection - Styles selected text
  • ::marker - Styles list markers
  • ::placeholder - Styles input placeholders

Basic Pseudo-elements Implementation

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CSS Basic Pseudo-elements</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    body {
      font-family: 'Inter', sans-serif;
      line-height: 1.6;
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      min-height: 100vh;
      padding: 2rem;
    }
    
    .container {
      max-width: 1200px;
      margin: 0 auto;
    }
    
    .header {
      text-align: center;
      margin-bottom: 3rem;
      color: white;
    }
    
    .header h1 {
      font-size: 3rem;
      margin-bottom: 1rem;
      text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
    }
    
    .demo-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
      gap: 2rem;
      margin-bottom: 3rem;
    }
    
    .demo-card {
      background: white;
      border-radius: 15px;
      padding: 2rem;
      box-shadow: 0 10px 30px rgba(0,0,0,0.2);
    }
    
    /* ::before and ::after examples */
    .quote {
      position: relative;
      padding: 1.5rem;
      background: #f8f9fa;
      border-radius: 10px;
      margin: 1rem 0;
    }
    
    .quote::before {
      content: "โ";
      font-size: 3rem;
      color: #3498db;
      position: absolute;
      top: -10px;
      left: 10px;
    }
    
    .quote::after {
      content: "โž";
      font-size: 3rem;
      color: #3498db;
      position: absolute;
      bottom: -20px;
      right: 10px;
    }
    
    /* ::first-letter example */
    .first-letter-demo::first-letter {
      font-size: 4rem;
      color: #e74c3c;
      float: left;
      line-height: 1;
      margin-right: 0.5rem;
      font-weight: bold;
    }
    
    /* ::first-line example */
    .first-line-demo::first-line {
      font-weight: bold;
      color: #2ecc71;
      font-size: 1.2rem;
    }
    
    /* ::selection example */
    .selection-demo::selection {
      background: #f39c12;
      color: white;
    }
    
    /* ::marker example */
    .marker-demo {
      padding-left: 2rem;
    }
    
    .marker-demo li::marker {
      color: #9b59b6;
      font-size: 1.2rem;
    }
    
    /* ::placeholder example */
    .placeholder-input {
      width: 100%;
      padding: 1rem;
      border: 2px solid #bdc3c7;
      border-radius: 5px;
      font-size: 1rem;
      margin: 1rem 0;
    }
    
    .placeholder-input::placeholder {
      color: #e74c3c;
      font-style: italic;
    }
    
    .code-example {
      background: #2c3e50;
      color: white;
      padding: 1rem;
      border-radius: 10px;
      margin-top: 1rem;
      font-family: monospace;
      font-size: 0.9rem;
    }
    
    .note {
      background: #fff3cd;
      border-left: 4px solid #ffc107;
      padding: 1rem;
      margin: 1rem 0;
      border-radius: 5px;
    }
    
    @media (max-width: 768px) {
      .demo-grid {
        grid-template-columns: 1fr;
      }
      
      .header h1 {
        font-size: 2rem;
      }
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="header">
      <h1>๐ŸŽฏ CSS Pseudo-elements</h1>
      <p>Style specific parts of elements with ::before, ::after, and more</p>
    </div>
    
    <div class="demo-grid">
      <div class="demo-card">
        <h3>::before & ::after</h3>
        <p>Add decorative content before and after elements:</p>
        
        <div class="quote">
          This is a beautiful quote demonstrating the power of pseudo-elements. 
          Notice the quotation marks added with ::before and ::after.
        </div>
        
        <div class="code-example">
          .quote::before {
            content: "โ";
            position: absolute;
            top: -10px;
            left: 10px;
          }
        </div>
      </div>
      
      <div class="demo-card">
        <h3>::first-letter</h3>
        <p>Style the first letter of a block of text:</p>
        
        <div class="first-letter-demo">
          This paragraph demonstrates the ::first-letter pseudo-element. 
          The first letter is styled differently to create a drop cap effect 
          commonly seen in magazines and books.
        </div>
        
        <div class="code-example">
          .first-letter-demo::first-letter {
            font-size: 4rem;
            color: #e74c3c;
            float: left;
          }
        </div>
      </div>
      
      <div class="demo-card">
        <h3>::first-line</h3>
        <p>Style the first line of a block of text:</p>
        
        <div class="first-line-demo">
          This paragraph shows the ::first-line pseudo-element in action. 
          The first line is styled with different color and weight. 
          Resize your browser to see how the styled portion changes dynamically 
          based on the first line of text.
        </div>
        
        <div class="code-example">
          .first-line-demo::first-line {
            font-weight: bold;
            color: #2ecc71;
          }
        </div>
      </div>
      
      <div class="demo-card">
        <h3>::selection</h3>
        <p>Style text when it's selected by the user:</p>
        
        <div class="selection-demo">
          Select this text to see the custom selection styling. 
          The background and text color change when you highlight this content.
        </div>
        
        <div class="code-example">
          .selection-demo::selection {
            background: #f39c12;
            color: white;
          }
        </div>
      </div>
      
      <div class="demo-card">
        <h3>::marker</h3>
        <p>Style list item markers (bullets/numbers):</p>
        
        <ul class="marker-demo">
          <li>First item with custom marker</li>
          <li>Second item with styled bullet</li>
          <li>Third item demonstrating ::marker</li>
        </ul>
        
        <div class="code-example">
          .marker-demo li::marker {
            color: #9b59b6;
            font-size: 1.2rem;
          }
        </div>
      </div>
      
      <div class="demo-card">
        <h3>::placeholder</h3>
        <p>Style placeholder text in form inputs:</p>
        
        <input type="text" class="placeholder-input" placeholder="Enter your text here...">
        
        <div class="code-example">
          .placeholder-input::placeholder {
            color: #e74c3c;
            font-style: italic;
          }
        </div>
      </div>
    </div>
    
    <div class="note">
      <strong>๐Ÿ’ก Note:</strong> Pseudo-elements use double colon syntax (::) in CSS3. 
      Single colon (:) is supported for backward compatibility with CSS2.
    </div>
  </div>
</body>
</html>

Creative Uses & Practical Applications

UI Components

Create tooltips, custom checkboxes, ribbons, and speech bubbles without JavaScript.

.tooltip:hover::before {
ย ย content: attr(data-tooltip);
ย ย position: absolute;
}

Decorative Elements

Add gradients, patterns, and complex shapes using multiple pseudo-elements.

.element::before, .element::after {
ย ย content: '';
ย ย /* complex styling */
}

Creative Uses Implementation

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Creative Pseudo-elements</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    body {
      font-family: 'Inter', sans-serif;
      line-height: 1.6;
      background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
      min-height: 100vh;
      padding: 2rem;
    }
    
    .container {
      max-width: 1200px;
      margin: 0 auto;
    }
    
    .header {
      text-align: center;
      margin-bottom: 3rem;
      color: white;
    }
    
    .header h1 {
      font-size: 3rem;
      margin-bottom: 1rem;
      text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
    }
    
    .creative-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
      gap: 2rem;
      margin-bottom: 3rem;
    }
    
    .creative-card {
      background: white;
      border-radius: 15px;
      padding: 2rem;
      box-shadow: 0 10px 30px rgba(0,0,0,0.2);
    }
    
    /* Tooltip with ::before */
    .tooltip {
      position: relative;
      display: inline-block;
      background: #3498db;
      color: white;
      padding: 0.5rem 1rem;
      border-radius: 5px;
      cursor: pointer;
    }
    
    .tooltip:hover::before {
      content: attr(data-tooltip);
      position: absolute;
      bottom: 100%;
      left: 50%;
      transform: translateX(-50%);
      background: #2c3e50;
      color: white;
      padding: 0.5rem 1rem;
      border-radius: 5px;
      white-space: nowrap;
      margin-bottom: 0.5rem;
    }
    
    .tooltip:hover::after {
      content: '';
      position: absolute;
      bottom: 100%;
      left: 50%;
      transform: translateX(-50%);
      border: 5px solid transparent;
      border-top-color: #2c3e50;
      margin-bottom: -5px;
    }
    
    /* Custom checkboxes */
    .checkbox-container {
      display: flex;
      flex-direction: column;
      gap: 1rem;
      margin: 1rem 0;
    }
    
    .custom-checkbox {
      position: relative;
      padding-left: 2.5rem;
      cursor: pointer;
    }
    
    .custom-checkbox input {
      position: absolute;
      opacity: 0;
    }
    
    .custom-checkbox .checkmark {
      position: absolute;
      left: 0;
      top: 0;
      height: 1.5rem;
      width: 1.5rem;
      background: #ecf0f1;
      border: 2px solid #bdc3c7;
      border-radius: 4px;
    }
    
    .custom-checkbox input:checked ~ .checkmark::after {
      content: "โœ“";
      position: absolute;
      color: #27ae60;
      font-size: 1.2rem;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
    }
    
    /* Ribbon with ::before and ::after */
    .ribbon {
      position: relative;
      background: #e74c3c;
      color: white;
      padding: 1rem 2rem;
      margin: 2rem 0;
      text-align: center;
    }
    
    .ribbon::before,
    .ribbon::after {
      content: '';
      position: absolute;
      bottom: -10px;
      border: 10px solid #c0392b;
    }
    
    .ribbon::before {
      left: 0;
      border-right-color: transparent;
    }
    
    .ribbon::after {
      right: 0;
      border-left-color: transparent;
    }
    
    /* Speech bubble */
    .speech-bubble {
      position: relative;
      background: #2ecc71;
      color: white;
      padding: 1.5rem;
      border-radius: 15px;
      margin: 2rem 0;
      max-width: 300px;
    }
    
    .speech-bubble::after {
      content: '';
      position: absolute;
      bottom: -10px;
      left: 20px;
      border: 10px solid transparent;
      border-top-color: #2ecc71;
    }
    
    /* Gradient borders with ::before */
    .gradient-border {
      position: relative;
      padding: 2rem;
      background: white;
      margin: 2rem 0;
    }
    
    .gradient-border::before {
      content: '';
      position: absolute;
      top: -3px;
      left: -3px;
      right: -3px;
      bottom: -3px;
      background: linear-gradient(45deg, #667eea, #764ba2);
      z-index: -1;
      border-radius: 10px;
    }
    
    /* Step indicator */
    .steps {
      display: flex;
      justify-content: space-between;
      position: relative;
      margin: 2rem 0;
    }
    
    .step {
      width: 40px;
      height: 40px;
      background: #bdc3c7;
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
      position: relative;
      z-index: 2;
    }
    
    .step.active {
      background: #3498db;
    }
    
    .steps::before {
      content: '';
      position: absolute;
      top: 50%;
      left: 20px;
      right: 20px;
      height: 3px;
      background: #bdc3c7;
      transform: translateY(-50%);
      z-index: 1;
    }
    
    .code-example {
      background: #2c3e50;
      color: white;
      padding: 1rem;
      border-radius: 10px;
      margin-top: 1rem;
      font-family: monospace;
      font-size: 0.8rem;
    }
    
    @media (max-width: 768px) {
      .creative-grid {
        grid-template-columns: 1fr;
      }
      
      .header h1 {
        font-size: 2rem;
      }
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="header">
      <h1>๐ŸŽจ Creative Pseudo-elements</h1>
      <p>Advanced techniques and practical applications</p>
    </div>
    
    <div class="creative-grid">
      <div class="creative-card">
        <h3>๐Ÿ’ฌ Tooltips</h3>
        <p>Hover over the button to see the tooltip:</p>
        <div class="tooltip" data-tooltip="This is a tooltip!">
          Hover me
        </div>
        <div class="code-example">
          .tooltip:hover::before {
            content: attr(data-tooltip);
            position: absolute;
            bottom: 100%;
          }
        </div>
      </div>
      
      <div class="creative-card">
        <h3>โ˜‘๏ธ Custom Checkboxes</h3>
        <p>Styled checkboxes using ::after:</p>
        <div class="checkbox-container">
          <label class="custom-checkbox">
            <input type="checkbox" checked>
            <span class="checkmark"></span>
            Option 1
          </label>
          <label class="custom-checkbox">
            <input type="checkbox">
            <span class="checkmark"></span>
            Option 2
          </label>
        </div>
        <div class="code-example">
          .custom-checkbox input:checked ~ .checkmark::after {
            content: "โœ“";
            position: absolute;
          }
        </div>
      </div>
      
      <div class="creative-card">
        <h3>๐ŸŽ€ Ribbons</h3>
        <p>Decorative ribbons using ::before and ::after:</p>
        <div class="ribbon">
          Special Offer
        </div>
        <div class="code-example">
          .ribbon::before, .ribbon::after {
            content: '';
            position: absolute;
            bottom: -10px;
          }
        </div>
      </div>
      
      <div class="creative-card">
        <h3>๐Ÿ’ญ Speech Bubbles</h3>
        <p>Chat-style bubbles with ::after:</p>
        <div class="speech-bubble">
          Hello! This is a speech bubble.
        </div>
        <div class="code-example">
          .speech-bubble::after {
            content: '';
            border: 10px solid transparent;
            border-top-color: #2ecc71;
          }
        </div>
      </div>
      
      <div class="creative-card">
        <h3>๐ŸŒˆ Gradient Borders</h3>
        <p>Gradient borders using ::before:</p>
        <div class="gradient-border">
          This div has a gradient border created with pseudo-elements.
        </div>
        <div class="code-example">
          .gradient-border::before {
            content: '';
            position: absolute;
            background: linear-gradient(...);
            z-index: -1;
          }
        </div>
      </div>
      
      <div class="creative-card">
        <h3>๐Ÿ”ข Step Indicators</h3>
        <p>Progress steps with ::before:</p>
        <div class="steps">
          <div class="step active">1</div>
          <div class="step">2</div>
          <div class="step">3</div>
        </div>
        <div class="code-example">
          .steps::before {
            content: '';
            position: absolute;
            top: 50%;
            background: #bdc3c7;
          }
        </div>
      </div>
    </div>
  </div>
</body>
</html>

Advanced Techniques

CSS Counters & Attribute Functions

Combine pseudo-elements with CSS counters for automatic numbering and use the attr() function to pull content from HTML attributes.

/* CSS Counters */
counter-reset: section;
h2::before {
ย ย counter-increment: section;
ย ย content: counter(section) ". ";
}

Advanced Techniques Implementation

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Advanced Pseudo-elements</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    body {
      font-family: 'Inter', sans-serif;
      line-height: 1.6;
      background: linear-gradient(135deg, #ff9a9e 0%, #fecfef 100%);
      min-height: 100vh;
      padding: 2rem;
    }
    
    .container {
      max-width: 1200px;
      margin: 0 auto;
    }
    
    .header {
      text-align: center;
      margin-bottom: 3rem;
      color: #2c3e50;
    }
    
    .header h1 {
      font-size: 3rem;
      margin-bottom: 1rem;
    }
    
    .advanced-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
      gap: 2rem;
      margin-bottom: 3rem;
    }
    
    .advanced-card {
      background: white;
      border-radius: 15px;
      padding: 2rem;
      box-shadow: 0 10px 30px rgba(0,0,0,0.2);
    }
    
    /* Counter with ::before */
    .counter-list {
      counter-reset: step-counter;
      list-style: none;
      padding: 0;
    }
    
    .counter-list li {
      counter-increment: step-counter;
      margin: 1rem 0;
      padding: 1rem;
      background: #f8f9fa;
      border-radius: 5px;
    }
    
    .counter-list li::before {
      content: counter(step-counter);
      background: #3498db;
      color: white;
      width: 2rem;
      height: 2rem;
      border-radius: 50%;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      margin-right: 1rem;
      font-weight: bold;
    }
    
    /* Attribute content with ::before */
    .attr-demo::before {
      content: attr(data-prefix) " " attr(data-content);
      display: block;
      background: #2ecc71;
      color: white;
      padding: 0.5rem;
      border-radius: 5px;
      margin-bottom: 1rem;
    }
    
    /* Multiple pseudo-elements */
    .fancy-heading {
      position: relative;
      text-align: center;
      margin: 2rem 0;
      padding: 1rem;
    }
    
    .fancy-heading::before,
    .fancy-heading::after {
      content: '';
      position: absolute;
      top: 50%;
      width: 30%;
      height: 2px;
      background: linear-gradient(90deg, transparent, #e74c3c, transparent);
    }
    
    .fancy-heading::before {
      left: 0;
    }
    
    .fancy-heading::after {
      right: 0;
    }
    
    /* Complex shapes with multiple pseudo-elements */
    .star-rating {
      display: flex;
      gap: 0.5rem;
      margin: 1rem 0;
    }
    
    .star {
      position: relative;
      width: 2rem;
      height: 2rem;
    }
    
    .star::before,
    .star::after {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background: #f39c12;
      clip-path: polygon(
        50% 0%, 61% 35%, 98% 35%, 68% 57%, 
        79% 91%, 50% 70%, 21% 91%, 32% 57%, 
        2% 35%, 39% 35%
      );
    }
    
    .star::after {
      background: #ecf0f1;
    }
    
    .star.filled::after {
      display: none;
    }
    
    /* Animated pseudo-elements */
    .loading-spinner {
      width: 4rem;
      height: 4rem;
      border: 4px solid #ecf0f1;
      border-top: 4px solid #3498db;
      border-radius: 50%;
      animation: spin 1s linear infinite;
      margin: 2rem auto;
    }
    
    @keyframes spin {
      0% { transform: rotate(0deg); }
      100% { transform: rotate(360deg); }
    }
    
    /* Complex background patterns */
    .pattern-box {
      position: relative;
      height: 150px;
      background: #34495e;
      margin: 2rem 0;
      border-radius: 10px;
      overflow: hidden;
    }
    
    .pattern-box::before,
    .pattern-box::after {
      content: '';
      position: absolute;
      width: 100px;
      height: 100px;
      background: rgba(255,255,255,0.1);
      border-radius: 50%;
    }
    
    .pattern-box::before {
      top: -50px;
      right: -50px;
    }
    
    .pattern-box::after {
      bottom: -50px;
      left: -50px;
    }
    
    /* Form validation with ::after */
    .form-group {
      margin: 1rem 0;
    }
    
    .form-input {
      width: 100%;
      padding: 1rem;
      border: 2px solid #bdc3c7;
      border-radius: 5px;
      font-size: 1rem;
    }
    
    .form-input:valid {
      border-color: #2ecc71;
    }
    
    .form-input:invalid {
      border-color: #e74c3c;
    }
    
    .form-input:focus:invalid::after {
      content: "Please check this field";
      color: #e74c3c;
      font-size: 0.8rem;
      display: block;
      margin-top: 0.5rem;
    }
    
    .code-example {
      background: #2c3e50;
      color: white;
      padding: 1rem;
      border-radius: 10px;
      margin-top: 1rem;
      font-family: monospace;
      font-size: 0.8rem;
    }
    
    @media (max-width: 768px) {
      .advanced-grid {
        grid-template-columns: 1fr;
      }
      
      .header h1 {
        font-size: 2rem;
      }
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="header">
      <h1>โšก Advanced Pseudo-elements</h1>
      <p>Complex techniques and real-world applications</p>
    </div>
    
    <div class="advanced-grid">
      <div class="advanced-card">
        <h3>๐Ÿ”ข CSS Counters</h3>
        <p>Automatic numbering with counters:</p>
        <ol class="counter-list">
          <li>First step in the process</li>
          <li>Second step with automatic numbering</li>
          <li>Third step demonstrating CSS counters</li>
          <li>Fourth step with custom markers</li>
        </ol>
        <div class="code-example">
          .counter-list {
            counter-reset: step-counter;
          }
          .counter-list li::before {
            content: counter(step-counter);
          }
        </div>
      </div>
      
      <div class="advanced-card">
        <h3>๐Ÿ“ Attribute Content</h3>
        <p>Using attr() function with pseudo-elements:</p>
        <div class="attr-demo" data-prefix="Info:" data-content="This content comes from data attributes">
          The content above is generated from HTML data attributes.
        </div>
        <div class="code-example">
          .attr-demo::before {
            content: attr(data-prefix) " " attr(data-content);
          }
        </div>
      </div>
      
      <div class="advanced-card">
        <h3>๐ŸŽญ Multiple Pseudo-elements</h3>
        <p>Single element with multiple pseudo-elements:</p>
        <h2 class="fancy-heading">Fancy Heading</h2>
        <div class="code-example">
          .fancy-heading::before, .fancy-heading::after {
            content: '';
            position: absolute;
            background: linear-gradient(...);
          }
        </div>
      </div>
      
      <div class="advanced-card">
        <h3>โญ Star Rating System</h3>
        <p>Interactive rating with pseudo-elements:</p>
        <div class="star-rating">
          <div class="star filled"></div>
          <div class="star filled"></div>
          <div class="star filled"></div>
          <div class="star"></div>
          <div class="star"></div>
        </div>
        <div class="code-example">
          .star::before, .star::after {
            content: '';
            clip-path: polygon(...);
          }
        </div>
      </div>
      
      <div class="advanced-card">
        <h3>๐ŸŒ€ Animated Spinners</h3>
        <p>Loading animation with pseudo-elements:</p>
        <div class="loading-spinner"></div>
        <div class="code-example">
          .loading-spinner {
            border: 4px solid #ecf0f1;
            border-top: 4px solid #3498db;
            animation: spin 1s linear infinite;
          }
        </div>
      </div>
      
      <div class="advanced-card">
        <h3>๐ŸŽจ Background Patterns</h3>
        <p>Complex backgrounds with pseudo-elements:</p>
        <div class="pattern-box"></div>
        <div class="code-example">
          .pattern-box::before, .pattern-box::after {
            content: '';
            position: absolute;
            background: rgba(255,255,255,0.1);
            border-radius: 50%;
          }
        </div>
      </div>
    </div>
    
    <div class="advanced-card">
      <h3>โœ… Form Validation</h3>
      <p>Visual feedback for form inputs:</p>
      <div class="form-group">
        <input type="email" class="form-input" placeholder="Enter valid email" required>
      </div>
      <div class="code-example">
        .form-input:invalid::after {
          content: "Please check this field";
          color: #e74c3c;
        }
      </div>
    </div>
  </div>
</body>
</html>

Best Practices & Browser Support

โœ… Do's

Use for decorative content, provide fallbacks, test accessibility

โŒ Don'ts

Don't add critical content, avoid overuse, consider performance

๐ŸŒ Support

Excellent browser support for most pseudo-elements

Best Practices Guide

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Pseudo-elements Best Practices</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    body {
      font-family: 'Inter', sans-serif;
      line-height: 1.6;
      background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
      min-height: 100vh;
      padding: 2rem;
    }
    
    .container {
      max-width: 1200px;
      margin: 0 auto;
    }
    
    .header {
      text-align: center;
      margin-bottom: 3rem;
      color: #2c3e50;
    }
    
    .header h1 {
      font-size: 3rem;
      margin-bottom: 1rem;
    }
    
    .practices-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
      gap: 2rem;
      margin-bottom: 3rem;
    }
    
    .practice-card {
      background: white;
      border-radius: 15px;
      padding: 2rem;
      box-shadow: 0 10px 30px rgba(0,0,0,0.2);
    }
    
    .do-dont {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 1rem;
      margin: 1rem 0;
    }
    
    .do {
      background: #d4edda;
      border: 2px solid #c3e6cb;
      padding: 1rem;
      border-radius: 5px;
    }
    
    .dont {
      background: #f8d7da;
      border: 2px solid #f5c6cb;
      padding: 1rem;
      border-radius: 5px;
    }
    
    .good-example, .bad-example {
      padding: 1rem;
      margin: 1rem 0;
      border-radius: 5px;
      font-family: monospace;
    }
    
    .good-example {
      background: #d1ecf1;
      border-left: 4px solid #17a2b8;
    }
    
    .bad-example {
      background: #f8d7da;
      border-left: 4px solid #dc3545;
    }
    
    .browser-support {
      background: #fff3cd;
      border: 2px solid #ffc107;
      padding: 1.5rem;
      border-radius: 10px;
      margin: 2rem 0;
    }
    
    .support-table {
      width: 100%;
      border-collapse: collapse;
      margin: 1rem 0;
    }
    
    .support-table th, .support-table td {
      border: 1px solid #dee2e6;
      padding: 0.5rem;
      text-align: center;
    }
    
    .support-table th {
      background: #f8f9fa;
    }
    
    .supported {
      background: #d4edda;
      color: #155724;
    }
    
    .partial {
      background: #fff3cd;
      color: #856404;
    }
    
    .not-supported {
      background: #f8d7da;
      color: #721c24;
    }
    
    .performance-tip {
      background: #e2e3e5;
      border-left: 4px solid #6c757d;
      padding: 1rem;
      margin: 1rem 0;
      border-radius: 5px;
    }
    
    @media (max-width: 768px) {
      .practices-grid {
        grid-template-columns: 1fr;
      }
      
      .do-dont {
        grid-template-columns: 1fr;
      }
      
      .header h1 {
        font-size: 2rem;
      }
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="header">
      <h1>๐Ÿ“š Pseudo-elements Best Practices</h1>
      <p>Guidelines for effective and maintainable code</p>
    </div>
    
    <div class="practices-grid">
      <div class="practice-card">
        <h3>๐ŸŽฏ Content Property</h3>
        <p>Always specify the content property for ::before and ::after:</p>
        
        <div class="do-dont">
          <div class="do">
            <strong>โœ… Do:</strong>
            <div class="good-example">
              .element::before {<br>
              &nbsp;&nbsp;content: "";<br>
              &nbsp;&nbsp;/* other styles */<br>
              }
            </div>
          </div>
          <div class="dont">
            <strong>โŒ Don&apos;t:</strong>
            <div class="bad-example">
              .element::before {<br>
              &nbsp;&nbsp;/* missing content property */<br>
              &nbsp;&nbsp;color: red;<br>
              }
            </div>
          </div>
        </div>
      </div>
      
      <div class="practice-card">
        <h3>๐Ÿ” Accessibility</h3>
        <p>Consider screen readers and accessibility:</p>
        
        <div class="do-dont">
          <div class="do">
            <strong>โœ… Do:</strong>
            <ul>
              <li>Use for decorative content only</li>
              <li>Provide text alternatives</li>
              <li>Test with screen readers</li>
            </ul>
          </div>
          <div class="dont">
            <strong>โŒ Don&apos;t:</strong>
            <ul>
              <li>Add critical content with pseudo-elements</li>
              <li>Hide important information</li>
              <li>Ignore accessibility testing</li>
            </ul>
          </div>
        </div>
      </div>
      
      <div class="practice-card">
        <h3>โšก Performance</h3>
        <p>Optimize for performance:</p>
        
        <div class="performance-tip">
          <strong>๐Ÿ’ก Tip:</strong> Pseudo-elements are generally performant, but avoid:
        </div>
        <ul>
          <li>Too many complex animations</li>
          <li>Excessive use of expensive CSS properties</li>
          <li>Nested pseudo-elements on many elements</li>
        </ul>
      </div>
      
      <div class="practice-card">
        <h3>๐ŸŽจ Maintainability</h3>
        <p>Write maintainable code:</p>
        
        <div class="do-dont">
          <div class="do">
            <strong>โœ… Do:</strong>
            <ul>
              <li>Use meaningful class names</li>
              <li>Comment complex implementations</li>
              <li>Keep pseudo-element styles together</li>
            </ul>
          </div>
          <div class="dont">
            <strong>โŒ Don&apos;t:</strong>
            <ul>
              <li>Overuse pseudo-elements</li>
              <li>Create overly complex designs</li>
              <li>Mix content and presentation</li>
            </ul>
          </div>
        </div>
      </div>
    </div>
    
    <div class="browser-support">
      <h3>๐ŸŒ Browser Support</h3>
      <table class="support-table">
        <thead>
          <tr>
            <th>Pseudo-element</th>
            <th>Chrome</th>
            <th>Firefox</th>
            <th>Safari</th>
            <th>Edge</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>::before, ::after</td>
            <td class="supported">1.0+</td>
            <td class="supported">1.5+</td>
            <td class="supported">3.1+</td>
            <td class="supported">8.0+</td>
          </tr>
          <tr>
            <td>::first-letter</td>
            <td class="supported">1.0+</td>
            <td class="supported">1.0+</td>
            <td class="supported">1.0+</td>
            <td class="supported">5.5+</td>
          </tr>
          <tr>
            <td>::first-line</td>
            <td class="supported">1.0+</td>
            <td class="supported">1.0+</td>
            <td class="supported">1.0+</td>
            <td class="supported">5.5+</td>
          </tr>
          <tr>
            <td>::selection</td>
            <td class="supported">1.0+</td>
            <td class="supported">1.5+</td>
            <td class="supported">1.1+</td>
            <td class="supported">9.0+</td>
          </tr>
          <tr>
            <td>::marker</td>
            <td class="supported">66+</td>
            <td class="supported">68+</td>
            <td class="supported">11.1+</td>
            <td class="supported">79+</td>
          </tr>
        </tbody>
      </table>
    </div>
    
    <div class="practice-card">
      <h3>๐Ÿš€ Pro Tips</h3>
      <div class="do-dont">
        <div class="do">
          <strong>Advanced Techniques:</strong>
          <ul>
            <li>Use attr() to get content from HTML attributes</li>
            <li>Combine with CSS counters for numbering</li>
            <li>Create complex shapes with multiple pseudo-elements</li>
            <li>Use for progressive enhancement</li>
          </ul>
        </div>
        <div class="dont">
          <strong>Common Pitfalls:</strong>
          <ul>
            <li>Forgetting content: "" for empty elements</li>
            <li>Overusing for critical content</li>
            <li>Ignoring browser support</li>
            <li>Creating inaccessible content</li>
          </ul>
        </div>
      </div>
    </div>
  </div>
</body>
</html>

Ready to Master Pseudo-elements? ๐ŸŽฏ

Experiment with pseudo-elements and discover how they can enhance your designs without cluttering your HTML. From simple decorations to complex UI components, pseudo-elements are powerful tools in your CSS arsenal.

< PreviousNext >