TheRogerLAB Codes

Card slider web component

  June, 2021

Introduction

This component consists in a card slider. Let's start by creating the structure of our web component. Create a file cardLab.js:

class cardLab extends HTMLElement {

  //Here will be all the functionality.

}
window.customElements.define('card-lab', cardLab);

Step 1: Add a constructor and a getter for noArrowsAt attribute

class cardLab extends HTMLElement {
  constructor () {
    super();
  }
  get noArrowsAt() {
    return this.hasAttribute('noArrowsAt');
  }
}
window.customElements.define('card-lab', cardLab);

Notice that noArrowsAt attribute is a breakpoint. If your card slider width is under or equal this value the arrows will be hidden.

Step 2: Add functions

class cardLab extends HTMLElement {
  //Step 1

  setSize(tot){
    //setting the total width
    this.shadowRoot.querySelector('.inner').style.width = tot + 'px';
    var ex = this.shadowRoot.querySelector('.external').offsetWidth;

    //always enable arrows
    this.shadowRoot.querySelector('.prev').style.display = 'block';
    this.shadowRoot.querySelector('.next').style.display = 'block';

    //disabling arrows if dont need to scroll
    if(tot <= ex){
      this.shadowRoot.querySelector('.prev').style.display = 'none';
      this.shadowRoot.querySelector('.next').style.display = 'none';
    }
    if(this.noArrowsAt){
      if(ex <= this.getAttribute('noArrowsAt')){
        this.shadowRoot.querySelector('.prev').style.display = 'none';
        this.shadowRoot.querySelector('.next').style.display = 'none';
      }
    }
  }
  stripPx(value) {
    if (value == ""return 0;
    return parseFloat(value.substring(0, value.length - 2));
  }
  mount(){
    //moving through the children cards
    var cards = this.children;
    var tot = 0;
    for (var i = 0; i < cards.length; i++) {
      //styling cards
      cards[i].style.backgroundColor = 'white';
      cards[i].style.cssFloat = 'left';
      cards[i].style.boxShadow = '0 4px 8px 0 rgba(0,0,0,0.2)';

      //finding total width
      var w = this.stripPx(cards[i].style.width);
      var m = this.stripPx(cards[i].style.marginRight);
      tot = tot + w + m;

      //calculating heights
      this.shadowRoot.querySelector('.main').style.height = cards[i].offsetHeight + 50 + 'px';
      this.shadowRoot.querySelector('.external').style.height = cards[i].offsetHeight + 20 + 'px';
      this.shadowRoot.querySelector('.prev').style.top = -(cards[i].offsetHeight / 2) - 80 + 'px';
      this.shadowRoot.querySelector('.next').style.top = -(cards[i].offsetHeight / 2) - 80 + 'px';
    }
    //setting the total width
    this.setSize(tot);
  } 
}
window.customElements.define('card-lab', cardLab);

Step 3: Add functions for arrows

class cardLab extends HTMLElement {
  //Step 1

  //Step 2

  next(){
    var nextA = this.shadowRoot.querySelector('.next');
    var prevA = this.shadowRoot.querySelector('.prev');
    var cards = this.children;
    var wc = this.stripPx(cards[0].style.width);
    var m = this.stripPx(cards[0].style.marginRight);
    var vis = this.shadowRoot.querySelector('.external').offsetWidth;
    var wt = this.shadowRoot.querySelector('.inner').offsetWidth;
    var wPerC = wt / cards.length;
    var scroll = this.shadowRoot.querySelector('.main').scrollLeft;
    for (var i = 0; i < cards.length; i++) {
      var leftC = i * wPerC;
      var cal = leftC - scroll + wc + m;
      if(cal > vis){
        this.shadowRoot.querySelector('.main').scrollTo({
          top: 0,
          left: leftC,
          behavior: 'smooth'
        });
        break;
      }
    }
  }
  prev(){
    var nextA = this.shadowRoot.querySelector('.next');
    var prevA = this.shadowRoot.querySelector('.prev');
    var cards = this.children;
    var vis = this.shadowRoot.querySelector('.external').offsetWidth;
    var wt = this.shadowRoot.querySelector('.inner').offsetWidth;
    var wPerC = wt / cards.length;
    var scroll = this.shadowRoot.querySelector('.main').scrollLeft;
    for (var i = 0; i < cards.length; i++) {
      var leftC = i * wPerC;
      var cal = leftC - scroll;
      if(cal < 0){
        if((cal * (-1)) < vis){
          this.shadowRoot.querySelector('.main').scrollTo({
            top: 0,
            left: leftC,
            behavior: 'smooth'
          });
          break;
        }
      }
    }
  }
}
window.customElements.define('card-lab', cardLab);

Step 4: Add a function connectedCallback

It fires when the component is created

class cardLab extends HTMLElement {
  //Step 1

  //Step 2

  //Step 3

  connectedCallback () {

    //Here will be the functionality.

  }
}
window.customElements.define('card-lab', cardLab);

Inside connectedCallback function we will create two things:

Filling the connectedCallback function:

class cardLab extends HTMLElement {
  //Step 1

  //Step 2

  //Step 3

  connectedCallback () {
    let shadowRoot = this.attachShadow({mode: 'open'});
    shadowRoot.innerHTML = `
    <style>
      .external{
        width:100%;
        overflow:hidden;
      }
      .main{
        overflow:auto;
        overflow-y:hidden;
      }
      .inner{
        padding-top: 10px;
        padding-left: 6px;
      }
      .prev{
        width: 60px;
        height: 60px;
        border-radius: 100px;
        position: relative;
        float: left;
        left: -26px;
        box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
        background-color:white;
        opacity: 0.9;
      }
      .next{
        width: 60px;
        height: 60px;
        border-radius: 100px;
        position: relative;
        top: -77%;
        float: right;
        left: 26px;
        box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
        background-color:white;
        opacity: 0.9;
      }
    </style>
    <div class='external' >
      <div class='main'>
        <div class='inner'>
          <slot name='card'></slot>
        </div>
      </div>
      <a class='prev'>
        <i style="position: relative;left: 34px;top: 19px;transform: rotate(135deg);-webkit-transform: rotate(135deg);border: solid black;border-width: 0 3px 3px 0;display: inline-block;padding: 3px;"></i>
      </a>
      <a class='next'>
        <i style="position: relative;left: 16px;top: 19px;transform: rotate(-45deg); -webkit-transform:rotate(-45deg);border: solid black;border-width: 0 3px 3px 0;display: inline-block;padding: 3px;"></i>
      </a>
    </div>`;
    //right arrow event
    shadowRoot.querySelector('.next').addEventListener('click', e => {
      this.next();
    });

    //left arrow event
    shadowRoot.querySelector('.prev').addEventListener('click', e => {
      this.prev();
    });

    //calling to mount
    this.mount();
  }
}
window.customElements.define('card-lab', cardLab);

Check a working demo for this code:

SEE DEMO RATE THIS ARTICLE
4.8
4
TheRogerLAB Codes
Powered by TheRogerLAB Sandbox

info@therogerlab.com