Air Quotes

79 of 123
Find some motivation with this demo about uplifting quotes inspired by air. This ZingGrid features card mode, expandable accordion content, and paging.
Result Full HTML CSS JS
Edit Download
“[[index.quote]]”— [[index.author]]

Biography sources: Wikipedia

Full Code

<!DOCTYPE html>
<html class="zg-html">

<head>
  <meta charset="utf-8">
  <title>ZingGrid: Simple Grid</title>
  <link href="https://fonts.googleapis.com/css?family=Muli:400,400i|Noto+Serif" rel="stylesheet">
  <script src="https://cdn.zinggrid.com/zinggrid.min.js" defer></script>
  <style>
    .zg-body {
      background: #e6e6e6;
      padding: 50px 0;
      font-family: 'Noto Serif', serif;
    }

    zing-grid {
      max-width: 1000px;
      margin: 0 auto;
      font-family: 'Noto Serif', serif;
      --theme-color-primary: #383838;
      background: none;
      color: #414141;
      border: none;
      opacity: 1;
      --zg-pager-font-size: 11px;
      --zg-row-body-background_hover: #f4fbff;
      --zg-row-color_hover: #383838;
    }

    zing-grid.loading {
      opacity: 0;
      transition: opacity .3s ease-out;
    }

    zg-caption {
      background: none;
      color: #414141;
      font-size: 40px;
      font-weight: bold;
      text-align: center;
      margin-bottom: 20px;
    }

    zg-body {
      background: none;
      color: #414141;
    }

    zg-row {
      background: #ffffff;
    }

    zg-row[layout="card"] {
      border-radius: 10px;
      -webkit-border-radius: 10px;
      -moz-border-radius: 10px;
      margin: 10px;
      box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.1), 0 6px 20px 0 rgba(0, 0, 0, 0.09);
    }

    zg-body[layout="card"] {
      --zg-card-columns: 33.3%;
    }

    .zg-body [data-field-index="author"] {
      align-items: center;
      justify-content: center;
      font-family: 'Muli', sans-serif;
    }

    zg-cell:nth-child(1) {
      font-size: 17px;
      line-height: 1.3;
      text-align: center;
    }

    zg-cell:nth-child(2) {
      font-size: 12px;
      line-height: 1.3;
      color: #a8a8a8;
    }

    zg-row[layout="row"] zg-cell:nth-child(1) {
      text-align: left;
    }

    zg-watermark {
      background: none;
      border: none;
      font-family: 'Muli', sans-serif;
      justify-content: center;
      font-size: 11px;
      margin-top: 10px;
    }

    zg-footer {
      font-family: 'Muli', sans-serif;
      text-align: center;
      font-size: 12px;
      margin-top: 20px;
    }

    .zg-body .accordion-flex-layout {
      --zg-cell-vertical-align: top;
    }

    /* target accordion for mobile and display as column*/

    .zg-body zing-grid[viewport="mobile"] .accordion-container {
      flex-direction: column;
      flex-grow: 1;
    }

    /* Main accordion styling */

    .zg-body .accordion input {
      display: none;
    }

    .zg-body .accordion label {
      position: relative;
      display: block;
      background: #f7f7f7;
      border-radius: .25em;
      cursor: pointer;
      margin-bottom: .125em;
      padding: .75rem 1em;
      z-index: 20;
      border: 1px solid #cccccc;
      text-align: center;
      font-size: 13px;
    }

    .zg-body .accordion label:hover {
      background: #ccc;
    }

    .zg-body .accordion input:checked+label {
      background: #dddddd;
      border-bottom-right-radius: 0;
      border-bottom-left-radius: 0;
      color: #383838;
      margin-bottom: -1px;
    }

    .zg-body .accordion label::after {
      content: '+';
      position: absolute;
      right: 5px;
    }

    .zg-body .accordion input:checked+label::after {
      content: '-';
      position: absolute;
      right: 5px;
    }

    .zg-body .accordion article {
      background: #f9f9f9;
      /* 
	 * max-height allows height transition in CSS 
	 * use height: 0px; otherwise
	 */
      max-height: 0px;
      overflow: hidden;
      z-index: 10;
      opacity: 0;
      /* allow closing transition */
      -webkit-transition: all 0.7s ease;
      -moz-transition: all 0.7s ease;
      -o-transition: all 0.7s ease;
      transition: all 0.7s ease;
      border: 1px solid #cccccc;
      color: #383838;
      font-size: 13px;
      line-height: 1.5;
    }

    .zg-body .accordion article {
      padding: 1em;
      cursor: default;
    }

    .zg-body .accordion input:checked~article {
      border-bottom-left-radius: .25em;
      border-bottom-right-radius: .25em;
      /* 
	 * max-height allows height transition in CSS 
	 * use height: auto; otherwise
	 */
      max-height: 500px;
      margin-bottom: .125em;
      opacity: 1;
      /* allow opening transition */
      -webkit-transition: all 1s ease;
      /* Safari */
      -moz-transition: all 1s ease;
      -o-transition: all 1s ease;
      transition: all 1s ease;
    }

    zing-grid[loading] {
      height: 996px;
    }
  </style>
</head>

<body class="zg-body">
  <zing-grid caption="Air Quotes" src="https://zinggrid-examples.firebaseio.com/air-quotes" layout="card" layout-controls="disabled" pager page-size="6" page-size-options="3,6,9,12" class="loading">
    <zg-colgroup>
      <zg-column index="quote" header=" ">
        “[[index.quote]]”
      </zg-column>
      <zg-column index="author" header=" "><em>— [[index.author]]</em></zg-column>
      <zg-column renderer="_bindAccordion" cell-class="accordion-flex-layout" index="author, bio" header=" ">
        <template>
            <section class="accordion">
              <input type="checkbox" id="changeme" >
              <label for="changeme">About the Author</label>
              <article>
                <p class="authorBio">[[index.bio]]</p>
              </article>
            </section>
          </template>
      </zg-column>
    </zg-colgroup>
    <zg-footer>
      <p>Biography sources: <a href="https://www.wikipedia.org/" target="_blank" crossorigin>Wikipedia</a>
    </zg-footer>
  </zing-grid>
  <script>
    // global event handler for expanding dropdowns
    const expandHandler = function() {
      this.classList.toggle('active');
      this.nextElementSibling.classList.toggle('show');
    }

    // generate randomId for dropdownsreturn Math.random().toString(36).replace(/[^a-z]+/g, '').substr(2, 10);
    const randomId = () => {
      return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(2, 10);
    }

    // custom render function for coach info accordion
    function _bindAccordion(name, bio, cellRef, $cell) {
      // grab template contents
      const $input = cellRef.querySelector('input');
      const $label = cellRef.querySelector('label');

      // assign template attributes and custom id's
      // so the label for will trigger the dropdown
      const dropdownID = randomId();
      $input.setAttribute('id', `accordion_${dropdownID}`);
      $label.setAttribute('for', `accordion_${dropdownID}`);
    };


    // Custom loading class for CSS handling
    const zgLoaded = document.querySelector('zing-grid');
    zgLoaded.addEventListener('grid:ready', () => {
      setTimeout(() => zgLoaded.classList.remove('loading'), 0);
    });
  </script>
</body>

</html>
<!DOCTYPE html>
<html class="zg-html">
  <head>
    <meta charset="utf-8">
    <title>ZingGrid: Simple Grid</title>
    <link href="https://fonts.googleapis.com/css?family=Muli:400,400i|Noto+Serif" rel="stylesheet">
    <script src="https://cdn.zinggrid.com/zinggrid.min.js" defer></script>
  </head>
  <body class="zg-body">
    <zing-grid
      caption="Air Quotes"
      src="https://zinggrid-examples.firebaseio.com/air-quotes"
      layout="card"
      layout-controls="disabled"
      pager
      page-size="6"
      page-size-options="3,6,9,12"
      class="loading"
    >
      <zg-colgroup>
        <zg-column index="quote" header=" ">
          “[[index.quote]]”
        </zg-column>
        <zg-column index="author" header=" "><em>— [[index.author]]</em></zg-column>
        <zg-column renderer="_bindAccordion" cell-class="accordion-flex-layout" index="author, bio" header=" ">
          <template>
            <section class="accordion">
              <input type="checkbox" id="changeme" >
              <label for="changeme">About the Author</label>
              <article>
                <p class="authorBio">[[index.bio]]</p>
              </article>
            </section>
          </template>
        </zg-column>
      </zg-colgroup>
      <zg-footer>
        <p>Biography sources: <a href="https://www.wikipedia.org/" target="_blank" crossorigin>Wikipedia</a>
      </zg-footer>
    </zing-grid>
  </body>
</html>
.zg-body {
  background:#e6e6e6;
  padding: 50px 0;
  font-family: 'Noto Serif', serif;
}

zing-grid {
	max-width: 1000px;
  margin: 0 auto;
  font-family: 'Noto Serif', serif;
  --theme-color-primary: #383838;
  background: none; 
  color: #414141;
  border: none;
  opacity: 1;
  --zg-pager-font-size: 11px;
  --zg-row-body-background_hover: #f4fbff;
  --zg-row-color_hover: #383838;
}
zing-grid.loading { opacity:0; transition:opacity .3s ease-out; }

zg-caption {
  background: none; 
  color: #414141;
  font-size: 40px;
  font-weight: bold;
  text-align: center;
  margin-bottom: 20px;
}

zg-body {
  background: none; 
  color: #414141;
}

zg-row {
  background: #ffffff;
}

zg-row[layout="card"] {
  border-radius: 10px;
  -webkit-border-radius: 10px;
  -moz-border-radius: 10px;
  margin: 10px;
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.1), 0 6px 20px 0 rgba(0, 0, 0, 0.09);
}

zg-body[layout="card"] {
  --zg-card-columns: 33.3%;
}

.zg-body [data-field-index="author"] {
  align-items: center;
  justify-content: center;
	font-family: 'Muli', sans-serif;
}

zg-cell:nth-child(1) {
  font-size: 17px;
  line-height: 1.3;
  text-align: center;
}

zg-cell:nth-child(2) {
  font-size: 12px;
  line-height: 1.3;
  color: #a8a8a8;
}

zg-row[layout="row"] zg-cell:nth-child(1) {
  text-align: left;
}

zg-watermark {
  background: none;
  border: none;
  font-family: 'Muli', sans-serif;
  justify-content: center;
  font-size: 11px;
  margin-top: 10px;
}

zg-footer {
  font-family: 'Muli', sans-serif;
  text-align: center;
  font-size: 12px;
  margin-top: 20px;
}

.zg-body .accordion-flex-layout {
  --zg-cell-vertical-align: top;
}

/* target accordion for mobile and display as column*/
.zg-body zing-grid[viewport="mobile"]  .accordion-container {
  flex-direction:column;
  flex-grow: 1;
}

/* Main accordion styling */
.zg-body .accordion input {
	display: none;
}

.zg-body .accordion label {
	position:relative;
  display: block;
	background: #f7f7f7;
	border-radius: .25em;
	cursor: pointer;
	margin-bottom: .125em;
	padding: .75rem 1em;
	z-index: 20;
  border: 1px solid #cccccc;
  text-align: center;
  font-size: 13px;
}

.zg-body .accordion label:hover {
	background: #ccc;
}

.zg-body .accordion input:checked + label {
	background: #dddddd;
	border-bottom-right-radius: 0;
	border-bottom-left-radius: 0;
	color: #383838;
	margin-bottom: -1px;
}

.zg-body .accordion label::after {
  content: '+';  
  position:absolute;
  right:5px;
}

.zg-body .accordion input:checked + label::after {
  content: '-';  
  position:absolute;
  right:5px;
}

.zg-body .accordion article {
	background: #f9f9f9;
	/* 
	 * max-height allows height transition in CSS 
	 * use height: 0px; otherwise
	 */
	max-height:0px;
	overflow:hidden;
	z-index:10;
	opacity:0;
	/* allow closing transition */
	-webkit-transition: all 0.7s ease; 
  -moz-transition: all 0.7s ease;
  -o-transition: all 0.7s ease;
	transition: all 0.7s ease;
  border: 1px solid #cccccc;
  color: #383838;
  font-size: 13px;
  line-height: 1.5;
}

.zg-body .accordion article {
	padding: 1em;
	cursor: default;
}

.zg-body .accordion input:checked ~ article {
	border-bottom-left-radius: .25em;
	border-bottom-right-radius: .25em;
	/* 
	 * max-height allows height transition in CSS 
	 * use height: auto; otherwise
	 */
	max-height: 500px;
	margin-bottom: .125em;
	opacity: 1;
	/* allow opening transition */
	-webkit-transition: all 1s ease; /* Safari */
  -moz-transition: all 1s ease;
  -o-transition: all 1s ease;
	transition: all 1s ease;
}
// global event handler for expanding dropdowns
const expandHandler = function() {
  this.classList.toggle('active');
  this.nextElementSibling.classList.toggle('show');
}

// generate randomId for dropdownsreturn Math.random().toString(36).replace(/[^a-z]+/g, '').substr(2, 10);
const randomId = () => {
  return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(2, 10);
}

// custom render function for coach info accordion
function _bindAccordion(name, bio, cellRef, $cell) {
  // grab template contents
  const $input = cellRef.querySelector('input');
  const $label = cellRef.querySelector('label');
  
  // assign template attributes and custom id's
  // so the label for will trigger the dropdown
  const dropdownID = randomId();
  $input.setAttribute('id', `accordion_${dropdownID}`);
  $label.setAttribute('for', `accordion_${dropdownID}`);
};


// Custom loading class for CSS handling
const zgLoaded = document.querySelector('zing-grid');
zgLoaded.addEventListener('grid:ready', () => {
  setTimeout(() => zgLoaded.classList.remove('loading'), 0);
});

Interested in this demo? Modify it to your needs in ZingSoft Studio, our testing sandbox. It's free to sign up, and you can come back and edit at any time!

Edit in Studio

Demo Gallery