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

              
                <div id="chemTable" class="chemTable">
  <div class="pageInfo">
    <h1>Periodic Table of Elements</h1>
    <h2>Click on an element to view more information</h2>
  </div>
<div class="element lanthanide actinide_spacer element_spacer">
  <div class="spacer_text">
    55-71
  </div>
</div>
  <div class="element actinide lanthanide_spacer element_spacer">
  <div class="spacer_text">
    89-103
  </div>
</div>
    <div class="extra_row_spacer">
</div>
    <div class="extra_row_background">
</div>
      
  </div>
<p>View the source files on Github at: <a href="https://github.com/rlahoda/css_grid_periodic_table">https://github.com/rlahoda/css_grid_periodic_table</a></p>
              
            
!

CSS

              
                @mixin respond-at($media) {
  @media only screen and (min-width: $media) {
    @content;
  }
}

$bp-xsmall: 600px;
$bp-small: 780px;
$bp-med: 1060px;
$bp-large: 1400px;

html {
  box-sizing: border-box;
}

*,
*::before,
*::after {
  box-sizing: inherit;
}
body {
  font-family: 'Raleway', sans-serif;
  background: #6190E8;  /* fallback for old browsers */
 background: -webkit-linear-gradient(to right, #A7BFE8, #6190E8);  /* Chrome 10-25, Safari 5.1-6 */
 background: linear-gradient(to right, #A7BFE8, #6190E8); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
}
h1 {
  font-size: 1.5em;
  &::first-letter {
    text-transform: capitalize;
  }
  @include respond-at($bp-med) {
    font-size: 2em;
  }
  @include respond-at($bp-large) {
    font-size: 4em;
  }
}
p {
  color: white;
}

.chemTable {
  font-family: 'Raleway', sans-serif;
  display: grid;
  grid-template-columns: repeat(18, 1fr);
  grid-template-rows: repeat(11, 60px);
  grid-gap: 0;
  padding: 1em;

    @include respond-at($bp-med) {
      grid-gap: 1em;
      grid-template-rows: repeat(11, 100px);
  }
}
.pageInfo {
  grid-column-start: 6;
 grid-column-end: 13;
 grid-row-start: 1;
 grid-row-end: 3;
 text-align: center;
}

.element {
  background-color: grey;
  opacity: 1;
  padding: 5px;
  display: grid;
  grid-template-rows: repeat(8, 1fr);
  grid-template-columns: repeat(6, 1fr);
  filter: drop-shadow(6px 6px 5px #555);
}

.atomicWeight {
 //   background-color:blue;
 text-align: left;
 font-size: 0.75em;
 grid-column-start: 1;
 grid-column-end: 2;
 grid-row-start: 1;
 grid-row-end: 2;
  display: flex;
justify-content: center; /* align horizontal */
align-items: center; /* align vertical */
.element_detail > & {
  font-size: 1.5em;
  grid-column-start: 1;
  grid-column-end: 4;
  grid-row-start: 4;
  grid-row-end: 5;
}
}

.elementSymbol {
//      background-color:green;
  font-family: 'Raleway', sans-serif;
 text-align: center;
 font-size: 1em;
 grid-column-start: 1;
 grid-column-end: -1;
 grid-row-start: 2;
 grid-row-end: 5;
  display: flex;
justify-content: center; /* align horizontal */
align-items: center; /* align vertical */
  @include respond-at($bp-med) {
    font-size: 1.5em;
  }
  @include respond-at($bp-large) {
    font-size: 2.2em;
  }
  .element_detail > & {
    font-size: 1.5em;
    font-family: 'Raleway', sans-serif;
    grid-column-start: 1;
    grid-column-end: 4;
    grid-row-start: 3;
    grid-row-end: 4;
  }
}

.elementName {
 //     background-color:blue;
 text-align: center;
 font-size: 0;
 grid-column-start: 1;
 grid-column-end: -1;
 grid-row-start: 5;
 grid-row-end: 8;
  font-family: 'Oswald', sans-serif;
  word-break: break-all;
  display: flex;
justify-content: center; /* align horizontal */
align-items: center; /* align vertical */
  @include respond-at($bp-small) {
    font-size: 0.75em;
  }
  // @include respond-at($bp-med) {
  //   grid-row-start: 5;
  // }
   @include respond-at($bp-large) {
    font-size: 0.8em;
     // grid-row-start: 6;
  }
  .element_detail > & {
    font-size: 2.5em;
    font-family: 'Raleway', sans-serif;
    grid-column-start: 2;
    grid-column-end: 6;
    grid-row-start: 1;
    grid-row-end: 3;
  }
}

.hidden {
  display: none;
  height: 0;
  width: 0;

  .element_detail & {
    display: inline;
    height: auto;
    width: auto;
    align-items: center;
    justify-content: center;
  }
}

.atomicMass {
//      background-color:green;
 text-align: center;
 font-size: 0;
 grid-column-start: 1;
 grid-column-end: -1;
 grid-row-start: 8;
 grid-row-end: -1;
 display: flex;
 justify-content: center; /* align horizontal */
 align-items: center; /* align vertical */
  font-family: 'Oswald', sans-serif;
  @include respond-at($bp-med) {
    font-size: 0.6em;
  }
  .element_detail > & {
    font-size: 1.5em;
    font-family: 'Raleway', sans-serif;
    grid-column-start: 1;
    grid-column-end: 4;
    grid-row-start: 5;
    grid-row-end: 6;
  }
}

.meltPoint {
//      background-color:green;
 text-align: center;
 font-size: 1.5em;
 grid-column-start: 1;
 grid-column-end: 4;
 grid-row-start: 7;
 grid-row-end: 8;
 display: flex;
 justify-content: center; /* align horizontal */
 align-items: center; /* align vertical */

  // @include respond-at($bp-med) {
  //   font-size: 0.6em;
  // }
}
.boilingPoint {
//      background-color:green;
 text-align: center;
 font-size: 1.5em;
 grid-column-start: 1;
 grid-column-end: 4;
 grid-row-start: 8;
 grid-row-end: 9;
 display: flex;
 justify-content: center; /* align horizontal */
 align-items: center; /* align vertical */

  // @include respond-at($bp-med) {
  //   font-size: 0.6em;
  // }
}

.elementCategory {
//      background-color:green;
 text-align: center;
 font-size: 1.5em;
 grid-column-start: 4;
 grid-column-end: -1;
 grid-row-start: 3;
 grid-row-end: 4;
 display: flex;
 justify-content: center; /* align horizontal */
 align-items: center; /* align vertical */

  // @include respond-at($bp-med) {
  //   font-size: 0.6em;
  // }
}

.density {
//      background-color:green;
 text-align: center;
 font-size: 1.5em;
 grid-column-start: 1;
 grid-column-end: 4;
 grid-row-start: 6;
 grid-row-end: 7;
 display: flex;
 justify-content: center; /* align horizontal */
 align-items: center; /* align vertical */

  // @include respond-at($bp-med) {
  //   font-size: 0.6em;
  // }
}

.summary {
//      background-color:green;
 text-align: left;
 font-size: 0.8em;
 line-height: 1.25;
 grid-column-start: 4;
 grid-column-end: -1;
 grid-row-start: 4;
 grid-row-end: 8;
 display: flex;
 justify-content: center; /* align horizontal */
 align-items: center; /* align vertical */

  @include respond-at($bp-med) {
    font-size: 1em;
  }
}

/* --- Categories of elements ---*/
.actinide {
 background-color: #e8ef54;
 color: black;
}

.alkali_metal {
 background-color: #85ef54;
 color: black;
}

.alkaline_earth_metal {
 background-color: #ef548c;
 color: white;
}

.diatomic_nonmetal {
 background-color: #3390ff;
 color: white;
}

.lanthanide {
 background-color: #8554ef;
 color: white;
}

.metalloid {
 background-color: #b769e4;
 color: white;
}

.noble_gas {
 background-color: #ee833e;
 color: white;
}

.polyatomic_nonmetal {
 background-color: #176cd1;
 color: white;
}

.post_transition_metal {
 background-color: #17d14f;
 color: white;
}

.transition_metal {
 background-color: #17d1ac;
 color: white;
}

.unknown_but_predicted_to_be_an_alkali_metal {
 background-color: #67a04d;
 color: white;
}

.unknown_predicted_to_be_noble_gas {
 background-color: #9b6b4b;
 color: white;
}

.unknown_probably_metalloid {
 background-color: #7d5892;
 color: white;
}

.unknown_probably_post_transition_metal {
 background-color: #79c48f;
 color: white;
}

.unknown_probably_transition_metal {
 background-color: #5db8a5;
 color: white;
}
/* --- Spacers--- */
.actinide_spacer {
 grid-column-start: 3;
 grid-column-end: 4;
 grid-row-start: 6;
 grid-row-end: 7;
}
.lanthanide_spacer {
 grid-column-start: 3;
 grid-column-end: 4;
 grid-row-start: 7;
 grid-row-end: 8;
}
.extra_row_spacer {
  background-color: pink;
  background: #6190E8;  /* fallback for old browsers */
background: -webkit-linear-gradient(to bottom, #A7BFE8, pink);  /* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to bottom, #A7BFE8, pink); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
  margin: -0.5em;
  grid-column-start: 3;
 grid-column-end: 4;
 grid-row-start: 6;
 grid-row-end: 9;
}
.extra_row_background {
  background-color: pink;
  margin: -0.5em;
  grid-column-start: 3;
 grid-column-end: 18;
 grid-row-start: 9;
 grid-row-end: 11;
}

.element_spacer {
  display: flex;
  justify-content: center;
align-items: center;
}

.spacer_text {
  text-align: center;
}
div.element_detail {
  grid-column-start: 3;
  grid-column-end: 17;
  grid-row-start: 1;
  grid-row-end: 12;
  z-index: 1000;
  margin: 2em;

  // @include respond-at($bp-small) {
  //  grid-column-start: 4;
  // grid-column-end: 16;
  // grid-row-start: 3;
  // grid-row-end: 9;
  // }

  @include respond-at($bp-med) {
  grid-column-start: 4;
  grid-column-end: 16;
  grid-row-start: 2;
  grid-row-end: 8;
  }
}

              
            
!

JS

              
                let elementId = "none";



function fcnDetails(id) { // This function adds and removes the CSS class that will make the elements show up in the details view. It uses a single parameter of the name of the element that was clicked on.
  let elId = "#"+id;
  let tl = new TimelineMax();
  tl.to(elId, 0.3, {opacity:0, scale: 0.5}, 0);
  tl.add(function() {
    console.log(elId);
    if (elementId != "none") { // First it checks to see if the elementId variable is not empty. If it's not, that means there is or was another element that was viewed in the details view.
      if (elementId != id) { // If the element name stored in elementId is not the same as the name of the element clicked on it looks for the element listed in elementId and removes the element_detail class from it. Then the element_detail class is added to the element that was clicked on.
        document.getElementById(elementId).classList.remove("element_detail");
        document.getElementById(id).classList.add("element_detail");
      } else {
        document.getElementById(id).classList.remove("element_detail"); // If the element name in elementId is the same as the one that was clicked on, that means the user clicked on the element details view, so the element_detail class is removed to return the element to the standard size
      }
    } else {
      document.getElementById(id).classList.add("element_detail"); // If the value of elementId is empty, then just add the element_detail class to the element that was clicked on
    }
    elementId = id;
    if (window.getSelection) {window.getSelection().removeAllRanges();} // For some reason, when I would click on elements, it would keep selecting random parts of the text. I'm not sure why it was happening, but it was so these two lines basically deselect any text that was being selected when the user clicks
   else if (document.selection) {document.selection.empty();}
   // TweenMax.from(".element", 0.5, {opacity:0});
  })
  tl.to(elId, 0.3, {opacity:1, scale: 1});
}

let info = []; // This creates an empty array for the information coming from the AJAX call to be stored in. This information will be used to generate the elements, add their information, set the colors, and set their position on the table

// To change the request, edit this url The first URL listed is the actual Github location of the original JSON. The second is a local version of the JSON if you have downloaded this project from Github
let url = "https://raw.githubusercontent.com/Bowserinator/Periodic-Table-JSON/master/PeriodicTableJSON.json";
// let url = "/scripts/elements.json";
// the ajax request
function ajax() {
  let xhr = new XMLHttpRequest();
  // console.log(xhr);
  xhr.open("GET", url, true);
  xhr.onreadystatechange = callback;
  // console.log(xhr.readyState, xhr.status, xhr.statusText);
  xhr.send();

  function callback() {
    // console.log(xhr.readyState, xhr.status, xhr.statusText);
    if (xhr.readyState == 4) {
      let response = JSON.parse(xhr.responseText);
      // console.log(response);
      info = response;
      // console.log(info.elements.length);
      elementBuilder();

    }
  }
}
window.onload = ajax;
// console.log(info);

function elementBuilder() {
  let style = document.createElement('style');
  let elementList = info.elements;
  let tl2 = new TimelineMax();
  tl2.pause();
  for (var element of elementList) { // This is a for..of loop that iterates over an iteratable object like an array or string or object. In this case it's iterating over the list of elements in the table and creating first the CSS then the HTML that will make up the table.
    // console.log(element);
    style.innerHTML += `.${element.name.toLowerCase()} {
      grid-column-start: ${element.xpos};
      grid-column-end: ${element.xpos === 18 ? `-1` : element.xpos + 1};
      grid-row-start: ${element.ypos};
      grid-row-end: ${element.ypos + 1};
    }`
//
    var elementStructure = `<div id="${element.name.toLowerCase()}" class="element ${element.category.toLowerCase().replace(/[^A-Z0-9]+/ig, "_")} ${element.name.toLowerCase()}" onmouseup="fcnDetails('${element.name.toLowerCase()}')">
    <div class="atomicWeight"><span class="hidden">Atomic Weight: </span> ${element.number}</div>
    <div class="elementSymbol"><span class="hidden">Symbol: </span> ${element.symbol}</div>
    <div class="elementName">${element.name}</div>
    <div class="atomicMass"><span class="hidden">Atomic Mass: </span> ${element.atomic_mass}</div>
    <div class="density"><span class="hidden">Density: ${element.density}</span></div>
    <div class="meltPoint"><span class="hidden">Melting Point: ${element.melt}</span></div>
    <div class="boilingPoint"><span class="hidden">Boiling Point: ${element.boil}</span></div>
    <div class="elementCategory"><span class="hidden">Element Category:<br> ${element.category}</span></div>
    <div class="summary"><span class="hidden">${element.summary}</span></div>
    </div>`;  // this is using template literals to build the structure of the element. The ".replace(/[^A-Z0-9]+/ig, "_")" is using regex to remove any spaces or characters that aren't numbers or letters and replace them with underscores.
    // I also used .toLowerCase() quite a bit to make sure there aren't any weird issues with different selectors coming in as different cases and not being correctly used.
    // console.log(elementStructure);
    let elementName = "."+element.name.toLowerCase();
    document.getElementById('chemTable').innerHTML += elementStructure;
    // tl2.from(".element", 0.5, {opacity:0}, Math.random() * 2);
  }

  let head = document.getElementsByTagName("head")[0].appendChild(style); // This looks in the document for the <head> tag, then in its children it adds the contents of the "style" variable, which is the variable that was used to store all of the CSS styles generated in the loop. This way the document ends up with a <style> tag in the <head> that has the specific styles needed to place each of the elements in their respective locations.
tl2.play();
TweenMax.staggerFrom(".element", 0.5, {opacity:0}, 0.05);
}

window.addEventListener('keypress', function(e) { // This adds a listener that looks for the user to press the "esc" key. If the user does, the function first checks to see if there's an element that has the same ID as the ID listed in the variable 'elementId'. If there is, it looks at the classes on it and removes the 'element_detail' class, which is the class used to show the element details view.
    if(e.key == "Escape"){
    	let id = document.getElementById(elementId);
      if (id) {
        id.classList.remove("element_detail");
      }
    }
});


              
            
!
999px

Console