Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ 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

Save Automatically?

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

              
                (Check the JS console)
              
            
!

CSS

              
                /* observe:; shorthand sets other properties */
one {
  --observe: width 200 medium 500 large;
}

two {
  --observe:
    width narrow 200 medium 500 wide,
    height short 200 medium 300 tall,
    children under 5 five 6 over
  ;
}

three {
  --observe: intersection-ratio 1 active;
}

/* Each condition has a property name */
one {
  --observe-width: 200 medium 500 large;
}

two {
  --observe-width: narrow 200 medium 500 wide;
  --observe-height: short 200 medium 300 tall;
  --observe-children: under 5 five 6 over;
}

three {
  --observe-intersection-ratio: .5 active;
}

/* testing overriding one with the other */
override with shorthand {
  --observe-width: 0 fail;
  --observe: width 100 success;
}

override shorthand {
  --observe: width 0 fail;
  --observe-width: 100 success;
}

/* all-in test of every condition */
valid examples {
  --observe-width: narrow 100 medium 200 wide;
  --observe-height: short 100 medium 200 tall;
  --observe-aspect-ratio: 1/1 equal 4/3 tv 16/9 widescreen;
  --observe-orientation: portrait tall square equal landscape wide;
  --observe-children: under 5 five 6 over;
  --observe-characters: okay 140 maximum 141 too-many;
  --observe-intersection-ratio: hidden 1/2 half-visible 1 fully-visible;
}
              
            
!

JS

              
                import {process, property} from 'https://unpkg.com/cssomtools'

// Conditions we support
const conditions = [
  'width',
  'height',
  'aspect-ratio',
  'orientation',
  'children',
  'characters',
  'intersection-ratio'
]

// Create a list of the breakpoints we find
const found = []

// How to parse a string like 'small 100 large' into {small: 0, large: 100}
function parseBreakpointString(breakpointString) {
  let list = breakpointString.trim().split(/\s+/)
  let breakpoints = {}

  // If odd length, that means string first
  // add a '0' as the minimum breakpoint now
  if (list.length % 2 !== 0) {
    list = ['0', ...list]
  }

  // Parse each […number, string*…] pair in array as {string: value}
  for (let i=0; i < list.length; i = i + 2) {
    breakpoints[list[i + 1]] = list[i]
  }

  return breakpoints
}

// How to parse a condition string
function parseConditionString(conditionString) {
  return conditionString
    .split(/,\s+/)
    .map(conditionString => 
      conditionString
        .split(new RegExp(`(${conditions.join('|')})`, 'g'))
        .filter(Boolean)
    )
}

// Process all rules accessible in CSSOM containing properties starting with '--observe'
process(
  property('--observe'),
  rule => {
  
    // We need to build an object containing lists of breakpoints for each condition
    // because we support a --observe shorthand as well as long form property names
    // we will need to process them in the order they appear
    const breakpoints = {}
    
    Array.from(rule.style)
      .filter(property => property.startsWith('--observe'))
      .forEach(property => {  
        const value = rule.style.getPropertyValue(property).trim()

        // Split apart and process each condition separately
        if (property === '--observe') {
          const list = parseConditionString(value)

          list.forEach(([condition, breakpointString]) =>
            breakpoints[condition] = parseBreakpointString(breakpointString)
          )

        // otherwise if the property is any other property we support
        } else {
          const conditionName = property.replace('--observe-', '')
          
          if (conditions.includes(conditionName)) {
            breakpoints[conditionName] = parseBreakpointString(value)
          }
        }
      
      })
    
    found.push(breakpoints)
  }
)

console.log(found)
              
            
!
999px

Console