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 CSS

These stylesheets will be added in this order and before the code you write in the CSS editor. You can also add another Pen here, and it will pull the CSS from it. Try typing "font" or "ribbon" below.

Quick-add: + add another resource

Add External JavaScript

These scripts will run in this order and before the code in the JavaScript editor. You can also link to another Pen here, and it will run the JavaScript from it. Also try typing the name of any popular library.

Quick-add: + add another resource

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.

            
              <div id="container">
  <div class="item grey"></div>
  <div class="item purple"></div>  
  <div class="item orange"></div>
  <div class="item blue"></div>
</div>
            
          
!
            
              #container{
  display: grid;
  width: 100%;
  height: 350px;
  grid-template-columns: [full-start] 1fr 1fr [full-end];
  grid-template-rows: 100px 1fr 100px;
  grid-gap: 20px;
}

.purple {
  grid-row: span 2;
}

.blue {
  grid-column: span 2;
}
            
          
!
            
              const container = document.getElementById("container");
const inspector = document.createElement('div');

inspector.setAttribute('style', `
  position: absolute;
  height: ${container.offsetHeight}px;
  width: ${container.offsetWidth}px;
  top: ${container.offsetTop}px;
  left: ${container.offsetLeft}px;
`);

document.body.appendChild(inspector);


// get the rows/columns/gaps
const styles = window.getComputedStyle(container);

const rows = styles.getPropertyValue("grid-template-rows");
const columns = styles.getPropertyValue("grid-template-columns");

const rowGap = styles.getPropertyValue("grid-row-gap");
const columnGap = styles.getPropertyValue("grid-column-gap");

// convert the rows and columns into a format we can work with
const columnData = parseGridTemplate(columns, columnGap);
const rowData = parseGridTemplate(rows, rowGap);

const extendLines = 20;

// render a line for each vertical grid line
columnData.forEach((item) => {
  const line = document.createElement('div');
  line.setAttribute('style', `
    background: black;
    position: absolute;
    height: ${container.offsetHeight + extendLines * 2}px;
    width: ${item.end - item.start + (item.gap || 0)}px;
    left: ${item.start}px;
    top: ${-extendLines}px;
  `);
   inspector.appendChild(line);
});

// render a line for each horizontal grid line
rowData.forEach((item) => {
  const line = document.createElement('div');
  line.setAttribute('style', `
    background: black;
    position: absolute;
    width: ${container.offsetWidth + extendLines * 2}px;
    height: ${item.end - item.start + (item.gap || 0)}px;
    top: ${item.start}px;
    left: ${-extendLines}px;
  `);
   inspector.appendChild(line);
});


/*
  Converts a grid template string into an array of grid line objects
  
  Example input: "[full-start] 300px 300px [full-end]"
     
  Example outut:
  [{
    "start": -1,
    "end": 1,
    "name": "full-start"
  },
  {
    "start": 299,
    "end": 301,
    "name": null,
    "gap": 20
  },
  {
    "start": 619,
    "end": 621,
    "name": "full-end"
  }]
*/
function parseGridTemplate(templateStr, gap = "0px") {
  
  const gapSize = parseFloat(gap.replace("px", ""));

  // splits at and space that isn't between two [ ] brackets
  const parsedArray = templateStr.split(/\s(?![^[]*])/);
  let lines = [];
  let currentPosition = 0;

  // add in any missing names as ""
  // "200px [center-start] 300px [center-end] 400px" becomes:
  // "'' 200px [center-start] 300px [center-end] 400px ''"

  let allItems = [];

  parsedArray.forEach((item, index) => {
    if (item.includes("px")) {
      // add a null name before it if missing
      if (!parsedArray[index - 1] || parsedArray[index - 1].includes("px")) {
        allItems.push("");
      }
    }

    allItems.push(item);
  });

  // handle last item
  if (parsedArray[parsedArray.length - 1].includes("px")) {
    allItems.push("");
  }

  allItems.forEach((item, index) => {
    if (item.includes("px")) {
      const trackSize = parseFloat(item.replace("px", ""));
      currentPosition += trackSize;
    } else {
      let newLine = {
        start: currentPosition - 1,
        end: currentPosition + 1,
        name: getName(item)
      };
      // add gaps on just the inner lines
      // and count it for positioning
      if (index !== 0 && index !== allItems.length - 1 && gapSize !== 0) {
        newLine.gap = gapSize;
        currentPosition += gapSize;
      }

      lines.push(newLine);
    }
  });

  return lines;
}

function getName(item) {
  return item.includes("[") ? item.match(/\[(.*)\]/)[1].trim() : null;
}
            
          
!
999px
Loading ..................

Console