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 is required to process package imports. If you need a different preprocessor remove all packages first.

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

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

              
                <head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
	<title>Periodic table</title>
</head>
<body>
	<div id="tableau">
    <div id="entete-period" class="opacity-zero">
      Period<br><span class="fleche">↓</span>
    </div>
    <div id="entete-group" class="opacity-zero">
      ←
      <p>Group</p>
      →
    </div>
    <div id="periode-0" class="periode">
      <a href="#" class="cel"></a>
    </div>
    <div id="periode-1" class="periode"></div>
    <div id="periode-2" class="periode"></div>
    <div id="periode-3" class="periode"></div>
    <div id="periode-4" class="periode"></div>
    <div id="periode-5" class="periode"></div>
    <div id="periode-6" class="periode">
      <div class="lanthanide opacity-zero">
        <div class="num">57 - 71</div>
        <div class="lan-act-fleche">↓</div>
        <div class="masse">Lanthanides</div>
      </div>
    </div>
    <div id="periode-7" class="periode">
      <div class="actinide opacity-zero">
        <div class="num">89 - 103</div>
        <div class="lan-act-fleche">↓</div>
        <div class="masse">Actinides</div>
      </div>
    </div>
    <div id="periode-8" class="periode"></div>
    <div id="periode-9" class="periode">
      <div class="lanthanides-row opacity-zero">
        <div class="lan-act-fleche">→</div>
        <div class="masse">Lanthanides</div>
      </div>
    </div>
    <div id="periode-10" class="periode">
      <div class="actinides-row opacity-zero">
        <div class="lan-act-fleche">→</div>
        <div class="masse">Actinides</div>
      </div>
    </div>
  </div>
  <div id="legende"></div>
  <div id="pres-element" class="invisible">
    <div class="pres-margin">
      <div id="pres-content">
        <!-- <div id="pres-bg"> -->
          <div id="description">
            <h2 id="presentation-nom"></h2>
            <div class="col">
              <div id="orbitales">
                <div id="orbites-set" class="set"></div>
                <div id="protons-set"></div>
              </div>
            </div>
            <div id="presentation-text" class="col">
              <div class="presentation-desc">
                <div id="pres-proton-text"></div>
                <div id="pres-elec-text"></div>
              </div>
              <table id="pres-elec-table">
                <thead><tr><th>Shells</th></tr></thead>
                <tbody><tr><th>Electrons</th></tr></tbody>
              </table>
              <div id="pres-carac-text"></div>
            </div>
          </div>
          <button id="close">&#10799;</button>
        <!-- </div> -->
      </div>
    </div>
  </div>
</body>
</html>
              
            
!

CSS

              
                @import url('https://fonts.googleapis.com/css?family=Archivo+Narrow&display=swap');

html {
 font-size: 16px;
 background-color: #000;
}
html, a {
 font-family: 'Archivo Narrow', sans-serif;
 font-weight: normal;
 font-style: normal;
 color: #093852;
}
#tableau .periode {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  margin-bottom: 3px;
}
#entete-period {
  position: absolute;
  color: #fff;
  width: 10%;
}
#entete-period .fleche {
  padding-left: 6%;
}
#entete-group {
  text-align: center;
  color: #fff;
}
#entete-group p {
  display: inline-block;
  margin: 0 17px;
}
#periode-8.periode {
  display: none;
}
.cel {
  flex-basis: 5%;
  max-width: 5%;
  margin-right: 0.1%;
  overflow: hidden;
  text-align: center;
  text-decoration: none;
  padding: 0.1%;
  position:relative;
  cursor: default;
}
.element {
  cursor: pointer;
}
.index {
  visibility: visible;
  color: #fff;
}
.cel[data-col='0'] .index-value {
  position: relative;
  top: 41%;
}
.cel[data-col='0'] {
  flex-basis: 1.5%;
}
#periode-0 .cel[data-col='0'],
#periode-9 .cel[data-col='0'],
#periode-10 .cel[data-col='0'] {
  visibility: hidden;
}
.display-name {
  visibility: visible;
  overflow: visible;
  color:#093852;
  filter: saturate(20);
}
.nom {
  font-size: 5em;
  opacity:0;
  position: absolute;
  top: -20%; 
  left: 70%;
  transition: opacity 1s ease;
}
.nom-visible {
  opacity:1;
}
.num {
  white-space: nowrap;
}
.symbol {
  font-size: 2em;
}
.masse {
  overflow: hidden;
}

#periode-6 .cel[data-col='3'],
#periode-7 .cel[data-col='3'],
#periode-9 .cel[data-col='2'],
#periode-10 .cel[data-col='2'] {
  visibility: visible;
  cursor: pointer;
}
#periode-9 .cel[data-col='2'],
#periode-10 .cel[data-col='2'] {
  text-align: right;
  overflow: visible;
  direction: rtl;
  color: #fff;
}
.lan-act-fleche {
  font-size: 2em;
}
#periode-9 .cel[data-col='2'] .lan-act-fleche,
#periode-10 .cel[data-col='2'] .lan-act-fleche {
  margin-top: 0.6em;
  color:#093852;
  filter: saturate(20);
}
#periode-9 .cel[data-col='2'] .masse,
#periode-10 .cel[data-col='2'] .masse {
  overflow: visible;
}
#periode-9 .cel[data-col='2'].unhover-arrow .lan-act-fleche, 
#periode-10 .cel[data-col='2'].unhover-arrow .lan-act-fleche {
  opacity: 0;
  transition: opacity 1s linear;
}
#periode-9 .cel[data-col='2'].hover-arrow .lan-act-fleche, 
#periode-10 .cel[data-col='2'].hover-arrow .lan-act-fleche {
  opacity: 1;
  transition: opacity 1s linear;
}
#periode-9 .cel[data-col='2'].unhover-arrow .masse, 
#periode-10 .cel[data-col='2'].unhover-arrow .masse {
  color:#fff;
  filter: saturate(1);
  transition: color 1.5s ease .2s, filter 1.5s ease .2s;
}
#periode-9 .cel[data-col='2'].hover-arrow .masse, 
#periode-10 .cel[data-col='2'].hover-arrow .masse {
  color:#093852;
  filter: saturate(20);
  transition: color 1.5s ease .2s, filter 1.5s ease .2s;
}
#legende {
  text-align: center;
  margin-top: 17px;
  color: #fff;
}
#legende div {
  display: inline-block;
}
.legende-famille {
  position: relative;
  overflow: hidden;
  margin-left: 7px;
}
.legende-coul {
  width: 21px;
  height: 21px;
  margin-right: 3px;
  position: relative;
  top: 2px;
}
.legende-nom {
  margin-right: 7px;
  height: 27px;
  vertical-align: middle;
}
.legende-nom-survol {
  color: #093852;
  filter: saturate(20);
  transition: color 1.5s ease .2s, filter 1.5s ease .2s;
}
.legende-nom-out {
  color: #fff;
  filter: saturate(1);
}
.legende-fond {
  position: absolute;
  top:2px;
  overflow: hidden;
  left: -100%;
  background-color: red;
  z-index: -1;
  width: 100%;
  height: 21px;
  opacity: .3;
}
.legende-survol {
  transform: translateX(100%);
  transition: transform 1s ease;
}
.legende-out {
  transform: translateX(-100%);
  transition: transform 0.7s ease-out;
}
.cel.element > div:first-child,
#periode-6 .cel[data-col='3'] > div.lanthanide,
#periode-7 .cel[data-col='3'] > div.actinide {
  transition: background-color 1s ease-out;
}
.cel .num,
.cel .symbol,
.cel .lan-act-fleche,
.cel .masse {
  filter: saturate(1);
  transition: filter 1s ease-out;
}
.cel:hover .num,
.cel:hover .symbol,
.cel:hover .lan-act-fleche,
.cel:hover .masse {
  filter: saturate(20);
}

.alkali-metal { background-color: rgb(64, 224, 208) }
.alkaline-earth-metal  { background-color: rgb(102, 207, 166) }
.transition-metal { background-color: rgb(140, 190, 125) }
.lanthanide { background-color: rgb(179, 174, 83) }
.actinide { background-color: rgb(217, 157, 41) }
.unknown { background-color: rgb(255, 140, 0) }
.metalloid  { background-color: rgb(255, 112, 26) }
.post-transition-metal { background-color: rgb(255, 84, 51) }
.polyatomic-nonmetal { background-color: rgb(255, 56, 77) }
.diatomic-nonmetal { background-color: rgb(255, 27, 103) }
.noble-gas { background-color: rgb(255, 1, 127) }

.cel:hover > .alkali-metal { background-color: rgba(64, 224, 208, 0.3) }
.cel:hover > .alkaline-earth-metal  { background-color: rgba(102, 207, 166, 0.3) }
.cel:hover > .transition-metal { background-color: rgba(140, 190, 125, 0.3) }
.cel:hover > .lanthanide { background-color: rgba(179, 174, 83, 0.3) }
.cel:hover > .actinide { background-color: rgba(217, 157, 41, 0.3) }
.cel:hover > .unknown { background-color: rgba(255, 140, 0, 0.3) }
.cel:hover > .metalloid  { background-color: rgba(255, 112, 26, 0.3) }
.cel:hover > .post-transition-metal { background-color: rgba(255, 84, 51, 0.3) }
.cel:hover > .polyatomic-nonmetal { background-color: rgba(255, 56, 77, 0.3) }
.cel:hover > .diatomic-nonmetal { background-color: rgba(255, 27, 103, 0.3) }
.cel:hover > .noble-gas { background-color: rgba(255, 1, 127, 0.3) }

.alkali-metal-back { background-color: rgba(106, 231, 218, 0.9) }
.alkaline-earth-metal-back { background-color: rgba(142, 220, 190, 0.9) }
.transition-metal-back { background-color: rgba(171, 207, 160, 0.9) }
.lanthanide-back { background-color: rgba(194, 190, 117, 0.9) }
.actinide-back { background-color: rgba(225, 178, 86, 0.9) }
.unknown-back { background-color: rgba(255, 163, 51, 0.9) }
.metalloid-back  { background-color: rgba(255, 144, 76, 0.9) }
.post-transition-metal-back { background-color: rgba(255, 127, 102, 0.9) }
.polyatomic-nonmetal-back { background-color: rgba(255, 107, 123, 0.9) }
.diatomic-nonmetal-back { background-color: rgba(255, 76, 136, 0.9) }
.noble-gas-back { background-color: rgba(255, 51, 152, 0.9) }

#pres-element {
  width: 100%;
  min-height: 100%;
  background-color: rgba(0,0,0,0.7);
  position: absolute;
  top: 0;
  left: 0;
}
.pres-margin {
  width: 94%;
  min-height: 94%;
  position: absolute;
  top: 3%;
  left: 3%;
}
#pres-content {
  min-width: 100%;
  min-height: 100%;
  position: absolute;
}
#description {
  overflow: hidden;
}
.invisible {
  display: none;
}
.visible {
  display: block;
}
.opacity-zero {
  opacity: 0;
}
.opacity-one {
  opacity: 1;
  transition: opacity ease;
}

#close {
  position: absolute;
  right: 0;
  top: 0;
  background: none;
  border: none;
  font-size: 2em;
  line-height: 1;
  transition: opacity 1s ease;
}
#close:hover {
  cursor:pointer;
  opacity:0.3;
}
#presentation-nom {
  font-size: 5em;
  margin: 0.3em 0 0;
  text-align: center;
}

.col {
  width: 47%;
  display: inline-block;
  vertical-align: top;
  margin-top: 35px;
  padding: 1%;
}
#orbitales {
  position: relative;
  margin: 0 auto;
  width: 47vw;
  height: 47vw;
  max-width: 600px;
  max-height: 600px;
}
.orbite {
  border-radius:50%;
  position: absolute;
  border: solid 1px #093852;
}

.electrons-set {
  width: 100%;
  height: 100%;
  position: absolute;
}
.electrons-set-start {
  transform: rotate(-180deg);
}
.electrons-set-transition:nth-child(odd) {
  transform: rotate(0deg);
}
.electrons-set-transition:nth-child(even) {
  transform: rotate(-360deg);
}
.electrons-set-transition {
  transition: transform ease;
}
.electron {
  border: solid 1px #093852;
  width: 3%;
  height: 3%;
  margin-right: 3px;
  position: absolute;
  display: inline-block;
  border-radius:50%;
  font-size:0.5em;
}
.proton {
  border: solid 1px #093852;
  width: 20%;
  height: 20%;
  margin-right: 3px;
  position: absolute;
  top: 40%;
  left: 40%;
  display: inline-block;
  border-radius:50%;
  font-size:0.5em;
}
.proton-text {
  width: 20%;
  position: absolute;
  top: 31%;
  left: 40%;
  text-align: center;
}
.pres-proton-text {
  display: none;
}
.presentation-desc {
  margin: 20px 0 10px;
  text-align: center;
}
table {
  border-collapse: collapse;
  margin: 0 auto;
}
thead tr {
  border-bottom: solid 1px #093852;
}
th, td {
  padding: 3px 7px;
}
th {
  text-align: left;
  border-right: solid 1px #093852;
  font-weight: normal;
}
td {
  text-align: center;
  min-width: 12px;
}

@keyframes fadeIn {
   0% {opacity: 0;}
   100% {opacity: 1;}
} 
@keyframes fadeOut {
   0% {opacity: 1;}
   100% {opacity: 0;}
} 

/* Responsive */

@media only screen and (max-width: 1450px) {
  #periode-6 .cel[data-col='3'] .masse,
  #periode-7 .cel[data-col='3'] .masse {
    visibility: hidden;
  }
}

@media only screen and (max-width: 1000px) {
  #periode-6 .cel[data-col='3'] .num,
  #periode-7 .cel[data-col='3'] .num {
    visibility: hidden;
  }
}

@media only screen and (max-width: 900px) {
  .nom {
    font-size: 4em;
  }
  .fleche-horizontale {
    display: none;
  }
}

@media only screen and (max-width: 800px) {
  #entete-group, #entete-period {
    visibility: hidden;
  }
  .proton-text {
    display: none;
  }
  .resp-proton-text {
    display: block;
  }
  .col {
    width: 100%;
  }
  #orbitales {
    width: 70vw;
    height: 70vw;;
  }
}

@media only screen and (max-width: 750px) {
  html {
    font-size: 14px;
  }
  .legende-coul {
    width: 15px;
    height: 15px;
  }
  .legende-nom {
    vertical-align: 2px;
  }
}

@media only screen and (max-width: 600px) {
  html {
    font-size: 12px;
  }
}

@media only screen and (max-width: 500px) {
  .periode:not(#periode-0) .cel {
    height: 52px;
  }
  .symbol, .lan-act-fleche {
    font-size: 1.5em;
  }
  .num, .masse {
    visibility: hidden;
  }
  .nom {
    font-size: 3em;
  }
  #periode-6 .cel[data-col='3'],
  #periode-7 .cel[data-col='3'] {
    max-height: 52px;
  }
}

@media only screen and (max-width: 400px) {
  #periode-6 .cel[data-col='3'],
  #periode-7 .cel[data-col='3'] {
    visibility: hidden;
  }
  .symbol {
    font-size: 1em;
    line-height: 2.5em;
  }
  .lan-act-fleche {
    visibility: hidden;
  }
  .nom {
    font-size: 2em;
  }
}

              
            
!

JS

              
                // based on Bowserinator/Periodic-Table-JSON
// https://github.com/Bowserinator/Periodic-Table-JSON/blob/master/PeriodicTableJSON.json

$(function() {

  const fadeInDuration = 1.5;

  // DOM elements to be created
  let $cels,
    $elements,
    $celDisplayName,
    $celDisplayLan,
    $celDisplayAct,
    $rowDisplayLan,
    $rowDisplayAct,
    $electronsSet,
    $currentElement;

  // cache DOM
  let $cel = $('.cel'),
    $tableau = $( '#tableau' ),
    $periode = $tableau.find( '.periode' ),
    $celLanthanidesText = $tableau.find( '.lanthanide' ),
    $celActinidesText = $tableau.find( '.actinide' ),
    $rowLanthanidesText = $tableau.find( '.lanthanides-row' ),
    $rowActinidesText = $tableau.find( '.actinides-row' ),
    $legende = $( '#legende' ),
    $orbitesSet = $( '#orbites-set' ),
    $protonsSet = $( '#protons-set' ),
    $presElem = $( '#pres-element' ),
    $presContent = $presElem.find( '#pres-content' ),
    $description = $presContent.find( '#description' ),
    $presNom = $description.find( '#presentation-nom' ),
    $presProtonText = $description.find( '#pres-proton-text' ),
    $presElecText = $description.find( '#pres-elec-text' ),
    $presElecTable = $description.find( '#pres-elec-table' ),
    $presCaracText = $description.find( '#pres-carac-text' ),
    $close = $presContent.find( '#close' );

  // Fn removing space and "é" from family name > create class names
  function createClass( chaine ) {

    chaine = chaine.split( ' ' ).join( '-' ).replace( /é/g, "e" );
    return chaine;
  }

  function transitionValues( index, duration, elemSet ) {
    // for each of the targeted elements, distribute animation delay and duration in order to have each set of elements fully animated at the end of the global duration 
    let elemCount = elemSet.length;
    let durationPerElem = duration / elemCount;
    let delay = durationPerElem * index;
    let newDuration = duration - delay;

    let transValues = {
      delay: delay,
      duration: newDuration,
    }

    return transValues;
  }

  function animate( elem, initialClass, newClass, duration ) {
  // animate function should be used only once on a set of elements
  // if used twice, css transition property should be all, delay & duration would be calculated twice
    elem.addClass( initialClass );

    setTimeout( function() { // delay transition return : avoid class interferences
      
      elem
        .removeClass( initialClass )
        .addClass( newClass )
        .each(function( index ) {

        let transValues = transitionValues( index, duration, elem );

        $( this )
          .css({ 
            'transition-delay': transValues.delay + 's',
            'transition-duration': transValues.duration + 's' 
          });
      });

    }, 100);

  };

  // add cels into the table
  let tableau = (function() {

    let celsToRemove = [ 
      $cel
    ];

    $( celsToRemove ).each(function() {
      $( this ).remove();
    });

    function appendCels( period, newCel ) {
      $( period ).append( newCel );
    };

    function addDataColIndex( period, cels ) {
      $( period ).find( cels ).each(function( index ) {
        $( this ).attr( 'data-col', index );
      });
    };

    $periode.each(function() {
      for ( let i = 0; i < 19; i++ ) {
        let newCel = $cel.clone();
        appendCels( this, newCel );
        $cels = $( '.cel' );
        addDataColIndex( this, $cels )
      }
    });

    function insertIndex( elem ) {
      elem.each(function( i ) {
        $( this )
          .addClass( 'index opacity-zero' )
          .html( '<span class="index-value">' + i + '</span>' );
      });
    };

    let celsIndex = [
      $( '#periode-0 .cel' ),
      $( '.cel[data-col="0"]' ),
    ];

    celsIndex.forEach(function( elem ) {
      insertIndex( elem );
    });

    $celDisplayLan = $( $periode[6] ).find( '[data-col="3"]' );
    $celDisplayAct = $( $periode[7] ).find( '[data-col="3"]' );
    $rowDisplayLan = $( $periode[9] ).find( '[data-col="2"]' );
    $rowDisplayAct = $( $periode[10] ).find( '[data-col="2"]' );

    $celDisplayLan.addClass( 'opacity-zero' ).html( $celLanthanidesText );
    $celDisplayAct.addClass( 'opacity-zero' ).html( $celActinidesText );
    $rowDisplayLan.addClass( 'unhover-arrow opacity-zero' ).html( $rowLanthanidesText );
    $rowDisplayAct.addClass( 'unhover-arrow opacity-zero' ).html( $rowActinidesText );

    $( $celDisplayLan ).children().removeClass( 'opacity-zero' );
    $( $celDisplayAct ).children().removeClass( 'opacity-zero' );
    $( $rowDisplayLan ).children().removeClass( 'opacity-zero' );
    $( $rowDisplayAct ).children().removeClass( 'opacity-zero' );

  })();


  // insert data in the table > called in dataElements
  function celsContent( index, elemValues ) {

    $currentElement = $( '#periode-' + elemValues.ypos + ' .cel[data-col="' + elemValues.xpos + '"]' );

    // add data for each cel containing element
    $currentElement
      .addClass( 'element' )
      .attr( 'data-atomic-number', elemValues.num )
      .html( `
        <div class="${elemValues.familleClass}">
          <div class="num">${elemValues.num}</div>
          <div class="symbol">${elemValues.symbol}</div>
          <div id="nom-${index+1}" class="nom">${elemValues.name}</div>
          <div class="masse">${elemValues.mass}</div>
        </div>
      ` )
      .click(function() {

        elemPresEmpty(); 
        elemPresCreation( elemValues ); 
        elemPresData( elemValues ); 
        elemPresDisplay( elemValues );
        elemPresAnim();
        
    });
  };

  // Display element names in an empty cel > called in dataElements
  let tableauNameDisplay = function() { 
    $celDisplayName = $( $periode[3] ).find( '[data-col="3"]' );
    $celDisplayName.addClass( 'display-name' );
    $( '.cel .nom' ).appendTo( $celDisplayName );
  };

  // create family legend > called in dataElements
  function insertLegend( legendFamUnique ) {
    
    $.each( legendFamUnique, function( index, value ) {

      let familleClass = createClass( value );
      $legende.append(`
        <div class="legende-famille opacity-zero">
          <div class="legende-coul ${familleClass}"></div>
          <div class="legende-fond ${familleClass} legende-out"></div>
          <div class="legende-nom legende-nom-out">${value}</div>
        </div>
      `)
    });
  }

  // hover effects on cels : elem name diplay, legend background slide and color change > called in dataElements
  function hoverCel() {

    // delay after cels appearence 
    setTimeout( function() {
    
      $elements = $( '.element' );
      
      $elements.each(function() {

        let atomNum = $( this ).attr( 'data-atomic-number' );
        let famille = $( 'div', this ).attr( 'class' );
        let $nomId = $( '#nom-' + atomNum );
        let $legendeFamilleFond = $( '#legende .' + famille + '.legende-fond' );
        let $legendeFamilleText = $legendeFamilleFond.next();
        
        $( this ).hover(function() {
          
          $nomId.addClass( "nom-visible" );
          $legendeFamilleFond.removeClass( "legende-out" ).addClass( "legende-survol" );
          $legendeFamilleText.removeClass( "legende-nom-out").addClass( "legende-nom-survol" );
        }, function() {
          $nomId.removeClass( "nom-visible" );
          $legendeFamilleFond.removeClass( "legende-survol" ).addClass( "legende-out" );
          $legendeFamilleText.removeClass( "legende-nom-survol").addClass( "legende-nom-out" );
        });
      });

      $( $celDisplayLan ).hover(function() {
        $rowDisplayLan.removeClass( "unhover-arrow" ).addClass( "hover-arrow" );
      }, function() {
        $rowDisplayLan.removeClass( "hover-arrow" ).addClass( "unhover-arrow" );
      });

      $( $celDisplayAct ).hover(function() {
        $rowDisplayAct.removeClass( "unhover-arrow" ).addClass( "hover-arrow" );
      }, function() {
        $rowDisplayAct.removeClass( "hover-arrow" ).addClass( "unhover-arrow" );
      });

    }, fadeInDuration * 1000 );

  }

  function animateCels( legendFamUnique ) {

    let famClassArray = [];

    $.each( legendFamUnique, function() {
      let famClass = createClass( this );
      famClassArray.push( famClass );
    });

    $.each( famClassArray, function() {
      let elems = $( '.' + this ).parent( '.element' );
      animate( elems, 'opacity-zero', 'opacity-one', fadeInDuration );
    });

    let notElems = [
      $( '#entete-period' ),
      $( '#entete-group' ),
      $( '.index' ),
      $celDisplayName,
      $celDisplayLan,
      $celDisplayAct,
      $rowDisplayLan,
      $rowDisplayAct,
      $( '.legende-famille' ),
    ];

    setTimeout( function() {
      $.each( notElems, function() {
        animate( this, 'opacity-zero', 'opacity-one', fadeInDuration );
      });
    }, fadeInDuration * 1000 );

  };

  /**
   * Elements presentation : pop-up when clicked
   */

  // empty previous data > called on click in celsContent()
  let elemPresEmpty = function() { 
    $( '.data-content' ).remove();
  };

  // insert new elements > called on click in celsContent()
  let elemPresCreation = function( elemValues ) {
    // for each shell, create orbital circles
    for ( let i = 0; i < elemValues.couches; i++ ) {
      $( '#orbitales' ).append( `<div class="electrons-set data-content"></div>` );
      $electronsSet = $( '.electrons-set' );
      let electrons = elemValues.couche[i];
      for ( let j = 0; j < electrons; j++ ) {
        $( $electronsSet[i] ).append( `<div class="electron ${elemValues.familleClass}"></div>` );
      }
      let $electron = $( $electronsSet[i] ).find( '.electron' );
      if ( $electron.length ) {
        $orbitesSet.prepend( '<div class="orbite data-content"></div>' );
      }
    }
    // create core
    $protonsSet.append( `<div class="proton ${elemValues.familleClass} data-content"></div>` );
  }

// insert data in element presentation > called on click in celsContent()
  let elemPresData = function( elemValues ) { 

    // add element data
    $presNom.append( `<span class="data-content">${elemValues.name}</span>` );
    $presProtonText.append( `<p class="data-content">${elemValues.protons} protons</p>` );
    $presElecText.append( `<p class="data-content">${elemValues.protons} electrons on ${elemValues.couches} shells</p>` );
    $presCaracText.append( `<ul class="data-content">
      <li><strong>Category</strong> : ${elemValues.famille}</li>
      <li><strong>Appearance</strong> : ${elemValues.appearance}</li>
      <li><strong>Atomic mass</strong> : ${elemValues.atomic_mass}</li>
      <li><strong>Boiling point</strong> : ${elemValues.boil} K</li>
      <li><strong>Density</strong> : ${elemValues.density} g/L</li>
      <li><strong>Discovered by</strong> : ${elemValues.discovered_by}</li>
      <li><strong>Melting point</strong> : ${elemValues.melt} K</li>
      <li><strong>Molar heat capacity</strong> : ${elemValues.molar_heat} J/(mol·K)</li>
      <li><strong>Named by</strong> : ${elemValues.named_by}</li>
      <li><strong>Atomic number</strong> : ${elemValues.num}</li>
      <li><strong>Period</strong> : ${elemValues.period}</li>
      <li><strong>Phase</strong> : ${elemValues.phase}</li>
      <li><strong>Source</strong> : <a href="${elemValues.source}" target="_blank">Wikipedia</a></li>
      <li><strong>Summary</strong> : ${elemValues.summary}</li>
      <li><strong>Symbol</strong> : ${elemValues.symbol}</li>
    </ul>` );

    // fill electron table
    for ( let i = 0; i < elemValues.couche.length; i++ ) {
      let tableIndex = i + 1;
      $presElecTable
        .find( 'thead tr' )
        .append( '<td class="data-content">' + tableIndex +'</td>' );
    }
    let electronsParCouches = elemValues.couche.map( electrons => ( 
      '<td class="data-content">' + electrons + '</td>' 
      ) );
    $presElecTable.find( 'tbody tr' ).append( electronsParCouches );

  }

  /**
   *  Placing & styling element > called on click in celsContent() 
   */

  let elemPresDisplay = function( elemValues ) {

    // show element window
    $presElem.fadeIn( 1000 );
    
    // add family classes for colors
    $presContent.removeClass().addClass( elemValues.familleClass +'-back' );
    $description.find( 'tr' ).each(function() {
      $( this ).find( 'td:odd' ).addClass( elemValues.familleClass );
    });

    // Orbitals/shells

    let 
      angles = [0],
      radius = [],
      margins = [];
    
    // 32 angle values por electron position
    for ( let i = 1; i < 32; i++ ) {
      let theta = ( ( 2 * Math.PI ) / 32 ) * i;
      angles.push( theta );
    }
    
    // 8 radius for the orbitals
    for ( let i = 1; i < 8; i++ ) {
      let rayon = 20 + ( ( 30 / 7 ) * i );
      radius.push( rayon );
    }

    // set orbitals size & place
    $( '.orbite' ).each(function( index ) {
      
      let size = radius[index] * 2 + '%';
      let margin = ( ( 100 - ( radius[index] * 2 ) ) / 2 );
      margins.push( margin );
      
      $( this ).css({
        'width' : size,
        'height' : size,
        'margin-left' : margin + '%',
        'margin-top' : margin + '%', 
      });
    });

    // get electron width, convert width in percentage
    let $electron = $( '.electron' )[0];
    let elemDiameter = parseFloat( $( $electron ).css( 'width' ) );
    elemDiameter = ( elemDiameter * 100 ) / parseFloat( $( $electron ).parent().css( 'width' ) );

    // Fn : radial css position
    function disqPos( elem, radius, angle, margin ) {

      $( elem ).css({
        'left' : 
          radius * ( Math.cos( angle )) // circle x position
          + radius // add radius, place it to the edge
          + margin // add parent margin
          - ( elemDiameter / 2 ) // remove electron radius
          + '%',
        'top' : 
          radius * ( Math.sin( angle )) // circle y position
          + radius // add radius, place it to the edge
          + margin // add parent margin
          - ( elemDiameter / 2 ) // remove electron radius
          + '%',            
      });

    }

    // Place electrons
    for ( let i = 0; i < elemValues.couches; i++ ) {

      let $electron = $( $electronsSet[i] ).find( '.electron' );
      $electron.each(function( index ) {

        disqPos( this, radius[i], angles[index], margins[i] );

      });
      
    }
  }

   // Animate presentation element > called on click in celsContent()

  let elemPresAnim = function() {

    const duration = 3; // Animation global duration

    const elemSetsToAnimate = [
      { elem: $presNom },
      { elem: $protonsSet },
      { elem: $electronsSet, rotation: true },
      { elem: $orbitesSet },
      { elem: $presProtonText },
      { elem: $presElecText },
      { elem: $presElecTable.find( 'th' ) },
      { elem: $( '#presentation-text table thead tr' ) },
      { elem: $( '#presentation-text table tbody tr' ) },
      { elem: $presCaracText.find( 'ul' ) }
    ];

    $( elemSetsToAnimate ).each(function() {

      let children = $( this.elem ).children();
      let initialClass = 'opacity-zero';
      let newClass = 'opacity-one';

      animate( children, initialClass, newClass, duration );

      if ( this.rotation == true ) {

        let elemToRotate = this.elem;
        let initialClass = 'electrons-set-start';
        let newClass = 'electrons-set-transition';

        animate( elemToRotate, initialClass, newClass, duration );
      }

    });

  }

  let closePresentation = (function() {
    $close.click(function() {
      $presElem.fadeOut( 500 );
    });
  })();


  let dataElements = (function() {

    // will contain the list of element categories
    let legendFam = []; 

    // reduce categories like "unknow, probably..." to one
    function uniqueUnknowFamily( chaine ) {
      if ( chaine.startsWith( "unknown" ) ) {
        chaine = "unknown";
      }
      return chaine;
    }

    $.ajax( {
      url: 'https://cdn.jsdelivr.net/gh/Bowserinator/Periodic-Table-JSON/PeriodicTableJSON.json',
      dataType: 'json',
      type:'get',
      success: function( data ) {

        $( data.elements ).each(function( index, value ) {
          
          let elemValues = {
            num: value.number,
            symbol: value.symbol,
            name: value.name,
            mass: value.atomic_mass,
            famille: value.category,
            familleUniqueUnknow: uniqueUnknowFamily( value.category ),
            familleClass: createClass( uniqueUnknowFamily( value.category ) ),
            appearance: value.appearance,
            atomic_mass: value.atomic_mass,
            boil: value.boil,
            density: value.density,
            discovered_by: value.discovered_by,
            melt: value.melt,
            molar_heat: value.molar_heat,
            named_by: value.named_by,
            period: value.period,
            phase: value.phase,
            source: value.source,
            summary: value.summary,
            couche: value.shells,
            couches: ( value.shells ).length,
            protons: value.number,
            xpos: value.xpos, 
            ypos: value.ypos,
          }
          
          legendFam.push( elemValues.familleUniqueUnknow );
          celsContent( index, elemValues );
          tableauNameDisplay();

        });

        let legendFamUnique = [...new Set( legendFam )]; // family : new array of unique names

        insertLegend( legendFamUnique );
        animateCels( legendFamUnique );
        hoverCel();

      }
    });
    
  })();
  
});
              
            
!
999px

Console