Skillversitas

CSS Box Shadow & Text Shadow

CSS shadows give elements and text a shadow effect to create depth, elevation, and visual emphasis. box-shadow works on the element's box, while text-shadow works on text.

Shadows are one of the most powerful tools for making a design feel "alive" — separating elements from the background, giving a 3D impression, and drawing attention to specific content.

Box-shadow components:

  • offset-x — horizontal offset (required)
  • offset-y — vertical offset (required)
  • blur-radius — how blurry the shadow is (optional, default 0)
  • spread-radius — how much the shadow expands (optional, default 0)
  • color — shadow color (optional, default inherit)
  • inset — creates the shadow inside the element

The text-shadow components are similar but without spread-radius.

Code Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CSS Box Shadow & Text Shadow</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
      background: #f0f2f5;
      padding: 40px 20px;
    }

    h1 {
      text-align: center;
      color: #1a1a2e;
      margin-bottom: 10px;
    }

    .subtitle {
      text-align: center;
      color: #888;
      margin-bottom: 50px;
    }

    .section {
      max-width: 900px;
      margin: 0 auto 60px;
    }

    .section h2 {
      color: #1a1a2e;
      margin-bottom: 25px;
      text-align: center;
      font-size: 1.3rem;
    }

    /* ===== Box Shadow Variations ===== */
    .shadow-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
      gap: 30px;
    }

    .shadow-item {
      background: white;
      border-radius: 12px;
      padding: 30px 20px;
      text-align: center;
    }

    .shadow-item h4 {
      font-size: 0.8rem;
      color: #667eea;
      margin-bottom: 8px;
      font-family: monospace;
    }

    .shadow-item p {
      font-size: 0.7rem;
      color: #aaa;
      font-family: monospace;
    }

    .shadow-box {
      width: 80px;
      height: 80px;
      background: white;
      border-radius: 12px;
      margin: 15px auto 0;
    }

    .sb-simple {
      box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    }

    .sb-medium {
      box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
    }

    .sb-large {
      box-shadow: 0 15px 50px rgba(0, 0, 0, 0.2);
    }

    .sb-colored {
      box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
    }

    .sb-spread {
      box-shadow: 0 0 0 8px rgba(102, 126, 234, 0.15);
    }

    .sb-inset {
      box-shadow: inset 0 4px 12px rgba(0, 0, 0, 0.15);
    }

    /* ===== Multiple Box Shadows ===== */
    .multi-shadow-section {
      background: white;
      border-radius: 16px;
      padding: 40px;
      box-shadow: 0 2px 10px rgba(0,0,0,0.06);
    }

    .multi-shadow-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
      gap: 30px;
    }

    .ms-item {
      text-align: center;
    }

    .ms-item h4 {
      font-size: 0.8rem;
      color: #667eea;
      margin-bottom: 15px;
    }

    .ms-box {
      width: 100px;
      height: 100px;
      margin: 0 auto;
      border-radius: 16px;
      background: linear-gradient(135deg, #667eea, #764ba2);
    }

    .ms-layered {
      box-shadow:
        0 2px 4px rgba(0,0,0,0.1),
        0 8px 16px rgba(0,0,0,0.1),
        0 24px 48px rgba(0,0,0,0.1);
    }

    .ms-colorful {
      box-shadow:
        -5px -5px 20px rgba(102, 126, 234, 0.4),
        5px 5px 20px rgba(118, 75, 162, 0.4);
    }

    .ms-neon {
      box-shadow:
        0 0 10px rgba(102, 126, 234, 0.5),
        0 0 20px rgba(102, 126, 234, 0.3),
        0 0 40px rgba(102, 126, 234, 0.2),
        0 0 80px rgba(102, 126, 234, 0.1);
    }

    .ms-soft {
      box-shadow:
        0 2px 2px rgba(0,0,0,0.04),
        0 4px 4px rgba(0,0,0,0.04),
        0 8px 8px rgba(0,0,0,0.04),
        0 16px 16px rgba(0,0,0,0.04),
        0 32px 32px rgba(0,0,0,0.04);
    }

    /* ===== Card Shadow Examples ===== */
    .card-shadow-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
      gap: 30px;
    }

    .card-shadow {
      border-radius: 16px;
      padding: 30px;
      background: white;
      transition: box-shadow 0.4s ease, transform 0.4s ease;
      cursor: pointer;
    }

    .card-flat {
      box-shadow: 0 1px 3px rgba(0,0,0,0.08);
    }

    .card-raised {
      box-shadow: 0 4px 12px rgba(0,0,0,0.1);
    }

    .card-floating {
      box-shadow: 0 12px 40px rgba(0,0,0,0.12);
    }

    .card-shadow:hover {
      transform: translateY(-8px);
    }

    .card-flat:hover {
      box-shadow: 0 4px 12px rgba(0,0,0,0.12);
    }

    .card-raised:hover {
      box-shadow: 0 12px 40px rgba(0,0,0,0.18);
    }

    .card-floating:hover {
      box-shadow: 0 20px 60px rgba(0,0,0,0.2);
    }

    .card-shadow h3 {
      color: #1a1a2e;
      margin-bottom: 10px;
    }

    .card-shadow p {
      color: #666;
      font-size: 0.85rem;
      line-height: 1.6;
    }

    .elevation-label {
      display: inline-block;
      padding: 4px 10px;
      background: #f0f2f5;
      border-radius: 4px;
      font-size: 0.7rem;
      font-family: monospace;
      color: #667eea;
      margin-bottom: 15px;
    }

    /* ===== Elevated Buttons ===== */
    .btn-elevated-grid {
      display: flex;
      gap: 20px;
      justify-content: center;
      flex-wrap: wrap;
    }

    .btn-elevated {
      padding: 14px 28px;
      border: none;
      border-radius: 8px;
      font-size: 1rem;
      font-weight: 600;
      cursor: pointer;
      transition: all 0.3s ease;
    }

    .btn-elev-1 {
      background: #667eea;
      color: white;
      box-shadow: 0 4px 0 #4a5fd4, 0 6px 12px rgba(102, 126, 234, 0.3);
    }

    .btn-elev-1:hover {
      transform: translateY(-2px);
      box-shadow: 0 6px 0 #4a5fd4, 0 10px 20px rgba(102, 126, 234, 0.4);
    }

    .btn-elev-1:active {
      transform: translateY(2px);
      box-shadow: 0 2px 0 #4a5fd4, 0 3px 6px rgba(102, 126, 234, 0.2);
    }

    .btn-elev-2 {
      background: #f5576c;
      color: white;
      box-shadow: 0 4px 0 #d43f52, 0 6px 12px rgba(245, 87, 108, 0.3);
    }

    .btn-elev-2:hover {
      transform: translateY(-2px);
      box-shadow: 0 6px 0 #d43f52, 0 10px 20px rgba(245, 87, 108, 0.4);
    }

    .btn-elev-2:active {
      transform: translateY(2px);
      box-shadow: 0 2px 0 #d43f52, 0 3px 6px rgba(245, 87, 108, 0.2);
    }

    .btn-elev-3 {
      background: #43e97b;
      color: #1a1a2e;
      box-shadow: 0 4px 0 #2bc763, 0 6px 12px rgba(67, 233, 123, 0.3);
    }

    .btn-elev-3:hover {
      transform: translateY(-2px);
      box-shadow: 0 6px 0 #2bc763, 0 10px 20px rgba(67, 233, 123, 0.4);
    }

    .btn-elev-3:active {
      transform: translateY(2px);
      box-shadow: 0 2px 0 #2bc763, 0 3px 6px rgba(67, 233, 123, 0.2);
    }

    /* ===== Text Shadow ===== */
    .text-shadow-section {
      background: linear-gradient(135deg, #1a1a2e, #16213e);
      border-radius: 16px;
      padding: 50px 30px;
      text-align: center;
    }

    .ts-basic {
      font-size: 2.5rem;
      font-weight: 900;
      color: white;
      text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
      margin-bottom: 25px;
    }

    .ts-long-shadow {
      font-size: 2.5rem;
      font-weight: 900;
      color: #667eea;
      text-shadow:
        1px 1px 0 #5a6fd4,
        2px 2px 0 #4e67c8,
        3px 3px 0 #425fbc,
        4px 4px 0 #3657b0,
        5px 5px 0 #2a4fa4;
      margin-bottom: 25px;
    }

    .ts-neon {
      font-size: 2.5rem;
      font-weight: 900;
      color: #fff;
      text-shadow:
        0 0 10px #667eea,
        0 0 20px #667eea,
        0 0 40px #667eea,
        0 0 80px #764ba2;
      margin-bottom: 25px;
    }

    .ts-glow {
      font-size: 2.5rem;
      font-weight: 900;
      color: #43e97b;
      text-shadow: 0 0 20px rgba(67, 233, 123, 0.8), 0 0 40px rgba(67, 233, 123, 0.4);
      margin-bottom: 25px;
    }

    .ts-outline {
      font-size: 2.5rem;
      font-weight: 900;
      color: transparent;
      -webkit-text-stroke: 2px #f5576c;
      text-shadow:
        3px 3px 0 rgba(245, 87, 108, 0.3),
        -1px -1px 0 rgba(245, 87, 108, 0.1);
      margin-bottom: 25px;
    }

    .ts-soft {
      font-size: 2rem;
      font-weight: 700;
      color: #fa709a;
      text-shadow: 0 2px 10px rgba(250, 112, 154, 0.5);
    }

    /* ===== Interactive Shadow Playground ===== */
    .playground {
      background: white;
      border-radius: 16px;
      padding: 40px;
      box-shadow: 0 2px 10px rgba(0,0,0,0.06);
    }

    .playground-preview {
      display: flex;
      justify-content: center;
      margin-bottom: 30px;
    }

    .playground-box {
      width: 150px;
      height: 150px;
      background: white;
      border-radius: 16px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 0.8rem;
      color: #aaa;
      transition: box-shadow 0.2s ease;
    }

    .playground-controls {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
      gap: 20px;
    }

    .control-group {
      display: flex;
      flex-direction: column;
    }

    .control-group label {
      font-size: 0.8rem;
      font-weight: 600;
      color: #555;
      margin-bottom: 5px;
    }

    .control-group input[type="range"] {
      accent-color: #667eea;
    }

    .control-group .value-display {
      font-size: 0.75rem;
      color: #667eea;
      font-family: monospace;
    }
  </style>
</head>
<body>

  <h1>CSS Box Shadow & Text Shadow</h1>
  <p class="subtitle">Shadow effects for depth and visual emphasis</p>

  <div class="section">
    <h2>Box Shadow Variations</h2>
    <div class="shadow-grid">
      <div class="shadow-item">
        <h4>Simple</h4>
        <div class="shadow-box sb-simple"></div>
        <p>0 4px 6px rgba(0,0,0,0.1)</p>
      </div>
      <div class="shadow-item">
        <h4>Medium</h4>
        <div class="shadow-box sb-medium"></div>
        <p>0 8px 25px rgba(0,0,0,0.15)</p>
      </div>
      <div class="shadow-item">
        <h4>Large</h4>
        <div class="shadow-box sb-large"></div>
        <p>0 15px 50px rgba(0,0,0,0.2)</p>
      </div>
      <div class="shadow-item">
        <h4>Colored</h4>
        <div class="shadow-box sb-colored"></div>
        <p>0 8px 25px rgba(102,126,234,0.4)</p>
      </div>
      <div class="shadow-item">
        <h4>Spread</h4>
        <div class="shadow-box sb-spread"></div>
        <p>0 0 0 8px rgba(102,126,234,0.15)</p>
      </div>
      <div class="shadow-item">
        <h4>Inset</h4>
        <div class="shadow-box sb-inset"></div>
        <p>inset 0 4px 12px rgba(0,0,0,0.15)</p>
      </div>
    </div>
  </div>

  <div class="section">
    <h2>Multiple (Layered) Box Shadows</h2>
    <div class="multi-shadow-section">
      <div class="multi-shadow-grid">
        <div class="ms-item">
          <h4>Layered</h4>
          <div class="ms-box ms-layered"></div>
        </div>
        <div class="ms-item">
          <h4>Colorful</h4>
          <div class="ms-box ms-colorful"></div>
        </div>
        <div class="ms-item">
          <h4>Neon Glow</h4>
          <div class="ms-box ms-neon"></div>
        </div>
        <div class="ms-item">
          <h4>Soft Stacked</h4>
          <div class="ms-box ms-soft"></div>
        </div>
      </div>
    </div>
  </div>

  <div class="section">
    <h2>Card Elevation Levels</h2>
    <div class="card-shadow-grid">
      <div class="card-shadow card-flat">
        <span class="elevation-label">elevation: flat</span>
        <h3>Flat</h3>
        <p>Minimal shadow — the card feels close to the background. Good for cards that do not need to stand out.</p>
      </div>
      <div class="card-shadow card-raised">
        <span class="elevation-label">elevation: raised</span>
        <h3>Raised</h3>
        <p>Medium shadow — the card feels lifted. Most commonly used for dashboard cards.</p>
      </div>
      <div class="card-shadow card-floating">
        <span class="elevation-label">elevation: floating</span>
        <h3>Floating</h3>
        <p>Large shadow — the card feels floating. Good for modals, dropdowns, or prominent elements.</p>
      </div>
    </div>
  </div>

  <div class="section">
    <h2>Elevated Buttons (3D Effect)</h2>
    <div class="btn-elevated-grid">
      <button class="btn-elevated btn-elev-1">Primary</button>
      <button class="btn-elevated btn-elev-2">Danger</button>
      <button class="btn-elevated btn-elev-3">Success</button>
    </div>
  </div>

  <div class="section">
    <h2>Text Shadow Effects</h2>
    <div class="text-shadow-section">
      <div class="ts-basic">Bayangan Dasar</div>
      <div class="ts-long-shadow">Long Shadow</div>
      <div class="ts-neon">Neon Glow</div>
      <div class="ts-glow">Soft Glow</div>
      <div class="ts-outline">Outline Text</div>
      <div class="ts-soft">Subtle & Clean</div>
    </div>
  </div>

  <div class="section">
    <h2>Interactive Shadow Playground</h2>
    <div class="playground">
      <div class="playground-preview">
        <div class="playground-box" id="previewBox">Preview</div>
      </div>
      <div class="playground-controls">
        <div class="control-group">
          <label>Offset X: <span class="value-display" id="oxVal">0</span>px</label>
          <input type="range" min="-30" max="30" value="0" id="ox" oninput="updateShadow()">
        </div>
        <div class="control-group">
          <label>Offset Y: <span class="value-display" id="oyVal">4</span>px</label>
          <input type="range" min="-30" max="30" value="4" id="oy" oninput="updateShadow()">
        </div>
        <div class="control-group">
          <label>Blur: <span class="value-display" id="blurVal">10</span>px</label>
          <input type="range" min="0" max="60" value="10" id="blur" oninput="updateShadow()">
        </div>
        <div class="control-group">
          <label>Spread: <span class="value-display" id="spreadVal">0</span>px</label>
          <input type="range" min="-20" max="20" value="0" id="spread" oninput="updateShadow()">
        </div>
      </div>
    </div>
  </div>

  <script>
    function updateShadow() {
      const ox = document.getElementById('ox').value;
      const oy = document.getElementById('oy').value;
      const blur = document.getElementById('blur').value;
      const spread = document.getElementById('spread').value;

      document.getElementById('oxVal').textContent = ox;
      document.getElementById('oyVal').textContent = oy;
      document.getElementById('blurVal').textContent = blur;
      document.getElementById('spreadVal').textContent = spread;

      const shadow = `${ox}px ${oy}px ${blur}px ${spread}px rgba(0,0,0,0.3)`;
      document.getElementById('previewBox').style.boxShadow = shadow;
    }
  </script>

</body>
</html>

Code Explanation

box-shadow Syntax

box-shadow: offset-x offset-y blur-radius spread-radius color;

The first two parameters are required (offset-x and offset-y). The rest are optional:

/* Basic */
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
/*         x  y   blur  color */

/* With spread */
box-shadow: 0 4px 6px 2px rgba(0,0,0,0.1);
/*         x  y   blur  spread  color */

/* Inset (inner shadow) */
box-shadow: inset 0 4px 6px rgba(0,0,0,0.1);

Offset X and Y

  • Positive offset-x = shadow to the right, negative = to the left
  • Positive offset-y = shadow below, negative = above
  • 0 0 = shadow directly behind the element
box-shadow: 4px 4px 10px rgba(0,0,0,0.2);  /* bottom-right */
box-shadow: -4px -4px 10px rgba(0,0,0,0.2); /* top-left */
box-shadow: 0 0 10px rgba(0,0,0,0.2);       /* center glow */

Blur Radius

Larger values = a blurrier, more spread-out shadow. Default is 0 (sharp edges).

box-shadow: 0 4px 0px rgba(0,0,0,0.2);  /* sharp */
box-shadow: 0 4px 20px rgba(0,0,0,0.2); /* blurred */
box-shadow: 0 4px 50px rgba(0,0,0,0.2); /* very blurred */

Spread Radius

Uniformly enlarges or shrinks the shadow. Positive = the shadow grows larger, negative = it shrinks.

box-shadow: 0 0 0 5px rgba(102,126,234,0.3); /* border-like effect */
box-shadow: 0 0 0 -3px rgba(102,126,234,0.3); /* shadow shrinks */

Multiple Box Shadows

You can add multiple shadows separated by commas — they are rendered in order (the first shadow is closest):

.box {
  box-shadow:
    0 2px 4px rgba(0,0,0,0.1),    /* close */
    0 8px 16px rgba(0,0,0,0.1),   /* middle */
    0 24px 48px rgba(0,0,0,0.1);  /* far */
}

Inset Box Shadow

The inset keyword creates the shadow inside the element — useful for "sunken" effects or inner glows:

.input {
  box-shadow: inset 0 2px 4px rgba(0,0,0,0.1);
}

/* Neumorphism: combination of inset and outset */
.neumorphic {
  box-shadow:
    6px 6px 12px rgba(0,0,0,0.15),
    -6px -6px 12px rgba(255,255,255,0.7);
}

text-shadow Syntax

text-shadow: offset-x offset-y blur-radius color;

Similar to box-shadow but without spread-radius and inset:

h1 {
  text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
  /*           x    y   blur  color */
}

Multiple Text Shadows

.neon-text {
  text-shadow:
    0 0 10px #667eea,
    0 0 20px #667eea,
    0 0 40px #667eea;
}

Everyday Use Cases

1. Card Elevation System

Creating a consistent elevation system for cards:

/* Material Design-like elevation */
.elevation-0 { box-shadow: none; }
.elevation-1 { box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.08); }
.elevation-2 { box-shadow: 0 3px 6px rgba(0,0,0,0.12), 0 2px 4px rgba(0,0,0,0.08); }
.elevation-3 { box-shadow: 0 10px 20px rgba(0,0,0,0.12), 0 3px 6px rgba(0,0,0,0.08); }
.elevation-4 { box-shadow: 0 14px 28px rgba(0,0,0,0.18), 0 5px 10px rgba(0,0,0,0.12); }

2. 3D Button Effect

A shadow that moves when the button is pressed — creating a 3D effect:

.btn-3d {
  background: #667eea;
  box-shadow: 0 6px 0 #4a5fd4, 0 8px 15px rgba(102,126,234,0.3);
  transition: all 0.1s ease;
}

.btn-3d:hover {
  box-shadow: 0 8px 0 #4a5fd4, 0 12px 20px rgba(102,126,234,0.4);
}

.btn-3d:active {
  transform: translateY(4px);
  box-shadow: 0 2px 0 #4a5fd4, 0 3px 6px rgba(102,126,234,0.2);
}

3. Glowing Text for Headings

Glowing text for prominent headings:

h1.glow {
  color: #667eea;
  text-shadow: 0 0 20px rgba(102, 126, 234, 0.6), 0 0 40px rgba(102, 126, 234, 0.3);
}

4. Neumorphism Design

Neumorphism design uses a combination of inset and outset shadows:

.neumorphic {
  background: #f0f0f0;
  box-shadow:
    8px 8px 16px #d1d1d1,
    -8px -8px 16px #ffffff;
}

.neumorphic-inset {
  box-shadow:
    inset 4px 4px 8px #d1d1d1,
    inset -4px -4px 8px #ffffff;
}

5. Focus Ring on Forms

A shadow as a focus indicator — more flexible than outline:

.input {
  border: 2px solid #ddd;
  transition: box-shadow 0.3s ease;
}

.input:focus {
  border-color: #667eea;
  box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.25);
}

Conclusion

box-shadow takes the parameters: offset-x, offset-y, blur-radius, spread-radius, and color. The inset keyword creates the shadow inside the element. Multiple shadows can be added, separated by commas, for a layered effect. text-shadow is similar but without spread-radius. Shadows are most often used for: card elevation, 3D button effects, glow effects, focus indicators, and neumorphism. Keys to good shadow design: use rgba() for transparency, stay consistent within an elevation system, and match the blur to the elevation size — the farther the shadow, the blurrier it should be.