Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <h1>Adam's list of Dynamic Styling Patterns</h1>

<div class="buttons">
  <span>Set Color:</span>
  
  <input type="radio" name="color" id="red" value="red" >
  <label for="red">Red</label>
  
  <input type="radio" name="color" id="green" value="green">
  <label for="green">Green</label>
  
  <input type="radio" name="color" id="teal" value="teal" >
  <label for="teal">Teal</label>
  
  <input type="radio" name="color" id="blue" value="blue">
  <label for="blue">Blue</label>
  
  <input type="radio" name="color" id="purple" value="purple" checked>
  <label for="purple">Purple</label>
</div>

<div class="pill-examples">
  
  <div class="example">
    
    <h1>Class-switched property assignment</h1>
    
    <p>Use JS to set a class. Directly update style declarations based on the class</p>
    
    <span class="pill" id="option-1">Pattern 1</span>
    
    <div class="pros"><b>Pros</b>: Simple</div>
    <div class="cons"><b>Cons</b>: All style declarations are rewritten (not DRY), Need to maintain the class list of possible values. Duplicated declarations (slightly) slow CSSOM construction.</div>
      
  </div>
  
  <div class="example">
    <h1>Class-switched Mixin call</h1>
    
    <p>Use JS to set a class. Call a mixin with the appropriate value based on the class.</p>
    
    <span class="pill" id="option-2">Pattern 2</span>
    
    <div class="pros"><b>Pros</b>: DRY - Style declarations are written once. Logic is done in pre-processor land</div>
    <div class="cons"><b>Cons</b>: Need to maintain the class list of possible values. Duplicated declarations are (slightly) slower</div>
    
  </div>

  
  
  <div class="example">
    <h1>Class-switched custom properties</h1>
    
    <p>Use JS to set a class. Set a custom property based on the class</p>

    <span class="pill" id="option-3">Pattern 3</span>
    
    <div class="pros"><b>Pros</b>: DRY - Style declarations are written once. Pure CSS (no pre-processor features)</div>
    <div class="cons"><b>Cons</b>: Need to maintain the class list of possible values</div>
    
  </div>

  
  <div class="example">
    <h1>JS switched custom properties</h1>
    
    <p>Use JS to set the custom property reference. Adam's favourite 🌟</p>

    <span class="pill" id="option-4">Pattern 4</span>
    
    <div class="pros"><b>Pros</b>: DRY - Style declarations are written once. Clean & minimal CSS and JS code</div>
    <div class="cons"><b>Cons</b>: Need to know the name of the CSS variables used</div>
    
  </div>
  
  
  <div class="example">
    <h1>JS defined custom property</h1>
    
    <p>Use JS to assign a value to the custom property</p>
    
    <span class="pill" id="option-5">Pattern 5</span>
    
    <div class="pros"><b>Pros</b>: Keeps logic in JS, DRY - Style declarations are written once.</div>
    <div class="cons"><b>Cons</b>: Need to store key/value map in JS</div>
  </div>
  
  <div class="example">
    <h1>Inline style manipulation</h1>
    
    <p>Use JS to set the style attribute directly</p>
    
    <span class="pill" id="option-6">Pattern 6</span>
    
    <div class="pros"><b>Pros</b>: Everything lives in JS, Technically faster to render.</div>
    <div class="cons"><b>Cons</b>: Potential specificity conflicts, Need to store key/value map in JS, Need to update each property — not DRY</div>
    
  </div>
  
  <div class="example">
    <!-- Thanks to Adam Argyle  - @argyleink for highlighting this approach -->
    <h1>CSSOM manipulation</h1>
    
    <p>Similar to inline styling, but here we use JS to <a href="https://developers.google.com/web/updates/2018/03/cssom">update the CSSOM directly</a>.</p>

    <span class="pill" id="option-7">Pattern 7</span>

    <div class="pros"><b>Pros</b>: Faster than inline, good unit type support</div>
    <div class="cons"><b>Cons</b>: Potential specificity conflicts, Need to store key/value map in JS, Need to update each property — not DRY. Limited browser support (Chrome & Edge)</div>
  </div>
  
  <div class="example">
    <!-- Thanks to Adam Argyle  - @argyleink for highlighting this approach -->
    <h1>Attribute switched custom properties</h1>
    
    <p>Similar to class-switching. Use JS to set an HTML attribute. Set a custom property based on that attribute</p>

    <span class="pill" id="option-8">Pattern 8</span>

    <div class="pros"><b>Pros</b>: Attributes are easier to update than classList, DRY - Style declarations are written once.</div>
    <div class="cons"><b>Cons</b>: Need to maintain all possible values in CSS</div>
  </div>  
  
</div>
              
            
!

CSS

              
                // Define base colors
:root {
  --color-red: #c20018;
  --color-green: #009b48;
  --color-teal: #0ac4ac;
  --color-blue: #0a4ace;
  --color-purple: #662d91;
}

// Option 1 — class-switched assignment
.pill#option-1 {
  outline-style: solid;
  outline-width: 1px;
  
  &.red { 
    background-color: var(--color-red);
    // ... other styles that rely on --color-*
  }
  &.green { 
    background-color: var(--color-green);
    // ... other styles that rely on --color-*
  }
  &.blue { 
    background-color: var(--color-blue);
    // ... other styles that rely on --color-*
  }
  &.teal { 
    background-color: var(--color-teal);
    // ... other styles that rely on --color-*
  }
  &.purple { 
    background-color: var(--color-purple);
    // ... other styles that rely on --color-*
  }
}

// Option 2 — class-switched Mixin
.pill#option-2 {
  @mixin pill-color($color) {
    background-color: var(--color-#{$color});
    // ... other styles that rely on --pill-color
  }
  
  &.red { @include pill-color('red')}
  &.green { @include pill-color('green')}
  &.blue { @include pill-color('blue')}
  &.teal { @include pill-color('teal')}
  &.purple { @include pill-color('purple')}
}

// Option 3 - class-switched custom properties
.pill#option-3 {
  
  &.red { --pill-color: var(--color-red) }
  &.green { --pill-color: var(--color-green) }
  &.blue { --pill-color: var(--color-blue) }
  &.teal { --pill-color: var(--color-teal) }
  &.purple { --pill-color: var(--color-purple) }
  
  background-color: var(--pill-color)
  // ... other styles that rely on --pill-color
}

// Option 4 - JS switched custom properties
.pill#option-4 {
  background-color: var(--pill-color)
  // ... other styles that rely on --pill-color
}

// Option 5 - JS defined custom property
.pill#option-5 {
  background-color: var(--pill-color)
  // ... other styles that rely on --pill-color
}

// Option 6 - Use inline styling
.pill#option-6 {}

// Option 7 - CSSOM manipulation
// https://developers.google.com/web/updates/2018/03/cssom
.pill#option-7 {}

// Option 8 - Attribute switching
.pill#option-8 {
  &[color="red"] { --pill-color: var(--color-red) }
  &[color="green"] { --pill-color: var(--color-green) }
  &[color="blue"] { --pill-color: var(--color-blue) }
  &[color="teal"] { --pill-color: var(--color-teal) }
  &[color="purple"] { --pill-color: var(--color-purple) }
  
  background-color: var(--pill-color)
  // ... other styles that rely on --pill-color
}

.pill {
  position: relative;
  font-size: 16px;
  padding: 0.25em 1em;
  border-radius: 1em;
  background-color: black;
  color: white;
  cursor: pointer;
  align-self: flex-start;
  justify-self: center;
  grid-row: 1 / 2;
  margin: 8px auto;
}

.pill-examples {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(32ch, 1fr));
  gap: 16px;
  width: 100%;
  
  .example {
    display: grid;
    gap: 8px;
    grid-auto-rows: max-content;
    padding: 16px;
    border: 1px solid #ccc;
    border-radius: 8px;
    background-color: white;
  }
  
  h1 {
    font-size: 20px;
    margin: 0;
    color: #161616;
  }
  
  p {
    margin: 0;
    color: #333;
  }
  
  .pros, .cons {
    font-size: 14px;
    color: #808080;
  }
}

body {
  font-family: Roboto, --apple-system, sans-serif;
  display: flex;
  width: 100vw;
  max-width: 1440px;
  flex-direction: column;
  gap: 16px;
  box-sizing: border-box;
  margin: 0 auto;
  padding: 24px;
  align-items: center;
  justify-content: center;
  background-color: #fafafe;
  color: #333;
}
              
            
!

JS

              
                setPillColors('purple')

function setPillColors(color) {
  
  // Option 1 - JS updated Class
  const option1 = document.querySelector('#option-1')
  clearClasses(option1)
  option1.classList.add(color)
  
  // Option 2 - JS updated Class w/ mixins
  const option2 = document.querySelector('#option-2')
  clearClasses(option2)
  option2.classList.add(color)

  // Option 3 - JS updated class w/ custom props
  const option3 = document.querySelector('#option-3')
  clearClasses(option3)
  option3.classList.add(color)

  // Option 4 - JS switched custom properties
  const option4 = document.querySelector('#option-4')
  option4.style.setProperty('--pill-color', `var(--color-${color})`)

  // Option 5 - JS assigned custom property
  const option5 = document.querySelector('#option-5')
  const COLOR_DEFS = {
    red: "#c20018",
    green: "#009b48",
    teal: "#0ac4ac",
    blue: "#0a4ace",
    purple: "#662d91",
  }
  option5.style.setProperty('--pill-color', COLOR_DEFS[color]) 
  
  // Option 6 - Direct styling
  const option6 = document.querySelector('#option-6')
  option6.style.backgroundColor = COLOR_DEFS[color]
  
  // Option 7 - attributeStyleMap
  const option7 = document.querySelector('#option-7')
  if(window.CSS && CSS.number) {
    option7.attributeStyleMap.set('background-color', COLOR_DEFS[color])
  }
  
  // Option 8 - attribute toggling
  const option8 = document.querySelector('#option-8');
  option8.setAttribute('color', color)
  
}

// Add listeners to the radio buttons
const radios = document.querySelectorAll('input[type="radio"][name="color"]')
radios.forEach(radio => radio.addEventListener('change', setColor))
function setColor({target : {value}}) {
  setPillColors(value)
}

// Remove all color classes from an element
// Not needed if using a framework like Vue, React, Angular etc.
function clearClasses(element) {
  element.classList.remove('red')
  element.classList.remove('green')
  element.classList.remove('teal')
  element.classList.remove('blue')
  element.classList.remove('purple')
}
              
            
!
999px

Console