cssAudio - Activefile-genericCSS - ActiveGeneric - ActiveHTML - ActiveImage - ActiveJS - ActiveSVG - ActiveText - Activefile-genericVideo - ActiveLovehtmlicon-new-collectionicon-personicon-teamlog-outoctocatpop-outspinnerstartv

Pen Settings

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

Looking for quick-add? Try the external resource search, it's quicker and gives you access to the most recent version of thousands of libraries. ☝️

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

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

Looking for quick-add? Try the external resource search, it's quicker and gives you access to the most recent version of thousands of libraries. ☝️

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation


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.

              <header class="header">
	<!--This block generated by a CMS -->
	<style type="text/css">
	.header {
		--headerBGColor: #993333; /*FIELD: backgroundColor*/
		--headerTitleColor: #daddad; /*FIELD: titleColor*/
		--headerSubtitleColor: #454545; /*FIELD: subTitleColor*/
		--headerRTFColor: var(--headerTextColor); /*NO FIELD*/
	<!--FIELD: IMAGE -->
	<picture class="header__media header__media--img">
		<source srcset="https://placebear.com/1500/500" media="(min-width:1200px)" />
		<source srcset="https://placebear.com/1000/500" media="(min-width:768px)" />
		<source srcset="https://placebear.com/400/500" media="(min-width: 400px)" />
	<img src="https://placebear.com/300/500" /> 
	<div class="header__hgroup">
		<!--FIELD: title -->
		<h1 class="header__title">This is a title, my color got overwritten</h1>
		<!--FIELD: subtitle -->
		<h2 class="header__subtitle">This is a smaller title, My color should have been the same as above, but it got changed</h2>
	<!--FIELD: description. Assumes rtf -->
	<div class="header__rtf rtf">
		<p> Here's a really smooth description and a <a href="#">link</a> you can use if you want </p>
              * {box-sizing: border-box}
img {width: 100%}
html {font-size: calc(12px + 1vmin)}

/*===LAYOUT ===*/
.header {
	position: relative;
	height: 500px;
	width: 100vw;
	padding: 0 .618rem;

.header__media {
	position: absolute; 
	top: 0; right: 0; bottom: 0; left: 0;
	z-index: 0;
	width: 100vw;
	height: 100vh;
	opacity: .8;

.header__hgroup {
	position: relative;
	z-index: 1;

@media (min-width: 768px) {
	.header__hgroup {
		width: 60%;

.header__subtitle {
	line-height: 1;

.header__title {
	font-size: 4rem;

.header__subtitle {
	font-size: 2rem;

.header__rtf {
	position: relative;
	z-index: 1;
	margin: 1em 0;

No variables created.  
This is more like "core brand"
None of this can be modified by end user
.header {
	font-family: Helvetica;
	text-shadow: 0px 1px 1px rgba(255,255,255, .3);

/* === MANAGED SKIN ===*/
Variables created in the outermost container because...
	...variable values 'cascade down' like anything else so...
	...Define variables once, apply many places
Assign variables to variables for flexible, but easily overwritten values
.header {
	--headerBGColor: #333;
	--headerTextColor: #cabbac;
	--headerTitleColor: var(--headerTextColor);
	--headerSubtitleColor: var(--headerTextColor); 
	--headerRTFColor: var(--headerTextColor);

.header {
	background-color: var(--headerBGColor);

.header__title {
	color: var(--headerTitleColor);

.header__subtitle {
	color: var(--headerSubtitleColor);

.header__rtf, .header__rtf * {
	color: var(--headerRTFColor);

              /* The following JavaScript, stolen, but with attribution, from: 
X Maybe account for defaults: color: var(--header-color, blue);
- Verify cross domain working or not (it is working from dropbox)
- Option to wait to apply anything until all <link>s are parsed or inject what we have and update as each <link> returns
- Need to test on a more complex CSS file
- Option to save parsed file in local/session storage so there isn't a delay on additional page loads. Could only do it for links (with URLs to use as keys) and style blocks with IDs of some sort
- Need to test more complex values like rgba(255,0,0,0.5); and something with !important
- Try multiple links
- Local links
- Ajax driven site, or CSS added later the top of the stack
let cssVarPoly = {
  init() {
    // first lets see if the browser supports CSS variables
    // No version of IE supports window.CSS.supports, so if that isn't supported in the first place we know CSS variables is not supported
    // Edge supports supports, so check for actual variable support
    if (window.CSS && window.CSS.supports && window.CSS.supports('(--foo: red)')) {
      // this browser does support variables, abort
      console.log('your browser supports CSS variables, aborting and letting the native support handle things.');
    } else {
      // edge barfs on console statements if the console is not open... lame!
      console.log('no support for you! polyfill all (some of) the things!!');

    cssVarPoly.ratifiedVars = {};
    cssVarPoly.varsByBlock = {};
    cssVarPoly.oldCSS = {};
    // start things off
  // find all the css blocks, save off the content, and look for variables
  findCSS() {
    let styleBlocks = document.querySelectorAll('style:not(.inserted),link[type="text/css"]');

    // we need to track the order of the style/link elements when we save off the CSS, set a counter
    let counter = 1;

    // loop through all CSS blocks looking for CSS variables being set
    [].forEach.call(styleBlocks, function(block) {
      // console.log(block.nodeName);
      let theCSS;
      if (block.nodeName === 'STYLE') {
        // console.log("style");
        theCSS = block.innerHTML;
        cssVarPoly.findSetters(theCSS, counter);
      } else if (block.nodeName === 'LINK') {
        // console.log("link");
        cssVarPoly.getLink(block.getAttribute('href'), counter, function(counter, request) {
          cssVarPoly.findSetters(request.responseText, counter);
          cssVarPoly.oldCSS[counter] = request.responseText;
        theCSS = '';
      // save off the CSS to parse through again later. the value may be empty for links that are waiting for their ajax return, but this will maintain the order
      cssVarPoly.oldCSS[counter] = theCSS;

  // find all the "--variable: value" matches in a provided block of CSS and add them to the master list
  findSetters(theCSS, counter) {
    // console.log(theCSS);
    cssVarPoly.varsByBlock[counter] = theCSS.match(/(--.+:.+;)/g) || [];

  // run through all the CSS blocks to update the variables and then inject on the page
  updateCSS() {
    // first lets loop through all the variables to make sure later vars trump earlier vars

    // loop through the css blocks (styles and links)
    for (let curCSSID in cssVarPoly.oldCSS) {
      // console.log("curCSS:",oldCSS[curCSSID]);
      let newCSS = cssVarPoly.replaceGetters(cssVarPoly.oldCSS[curCSSID], cssVarPoly.ratifiedVars);
      // put it back into the page
      // first check to see if this block exists already
      if (document.querySelector('#inserted' + curCSSID)) {
        // console.log("updating")
        document.querySelector('#inserted' + curCSSID).innerHTML = newCSS;
      } else {
        // console.log("adding");
        var style = document.createElement('style');
        style.type = 'text/css';
        style.innerHTML = newCSS;
        style.id = 'inserted' + curCSSID;

  // parse a provided block of CSS looking for a provided list of variables and replace the --var-name with the correct value
  replaceGetters(curCSS, varList) {
    // console.log(varList);
    for (let theVar in varList) {
      // console.log(theVar);
      // match the variable with the actual variable name
      let getterRegex = new RegExp('var\\(\\s*' + theVar + '\\s*\\)', 'g');
      // console.log(getterRegex);
      // console.log(curCSS);
      curCSS = curCSS.replace(getterRegex, varList[theVar]);

      // now check for any getters that are left that have fallbacks
      let getterRegex2 = new RegExp('var\\(\\s*.+\\s*,\\s*(.+)\\)', 'g');
      // console.log(getterRegex);
      // console.log(curCSS);
      let matches = curCSS.match(getterRegex2);
      if (matches) {
        // console.log("matches",matches);
        matches.forEach(function(match) {
          // console.log(match.match(/var\(.+,\s*(.+)\)/))
          // find the fallback within the getter
          curCSS = curCSS.replace(match, match.match(/var\(.+,\s*(.+)\)/)[1]);


      // curCSS = curCSS.replace(getterRegex2,varList[theVar]);
    // console.log(curCSS);
    return curCSS;

  // determine the css variable name value pair and track the latest
  ratifySetters(varList) {
    // console.log("varList:",varList);
    // loop through each block in order, to maintain order specificity
    for (let curBlock in varList) {
      let curVars = varList[curBlock];
      // console.log("curVars:",curVars);
      // loop through each var in the block
      curVars.forEach(function(theVar) {
        // console.log(theVar);
        // split on the name value pair separator
        let matches = theVar.split(/:\s*/);
        // console.log(matches);
        // put it in an object based on the varName. Each time we do this it will override a previous use and so will always have the last set be the winner
        // 0 = the name, 1 = the value, strip off the ; if it is there
        cssVarPoly.ratifiedVars[matches[0]] = matches[1].replace(/;/, '');
    // console.log(ratifiedVars);

  // get the CSS file (same domain for now)
  getLink(url, counter, success) {
    var request = new XMLHttpRequest();
    request.open('GET', url, true);
    request.onload = function() {
      if (request.status >= 200 && request.status < 400) {
        // Success!
        // console.log(request.responseText);
        if (typeof success === 'function') {
          success(counter, request);
      } else {
        // We reached our target server, but it returned an error
        console.warn('an error was returned from:', url);

    request.onerror = function() {
      // There was a connection error of some sort
      console.warn('we could not get anything from:', url);


// hash = function(s){
//   return s.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0);              
// }

// export default makeFit;

// stuff for hiding documentation for Opera Mini testing
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.
Loading ..................