Slider

The slider is a proposed replacement for what is commonly referred to as a carousel. It consists of multiple slides which can expand upon user focus or interaction. It differ from the classic carousel in that all its slide are always visible, even when one of them is expanded.

Slider: Fallback

Component Preview
<div class="slider">
    <div tabindex="0" class="slider__slide" aria-expanded="true">

        <div class="banner  banner--medium banner--reversed vertical-bottom horizontal-left">
            <div class="banner__image">
                <img src="https://sandbox.prod.drupal.uiowa.edu/sites/sandbox.uiowa.edu/files/2021-03/feature3.jpg">
            </div>

            <div class="banner__container">
                <div class="banner__content">

                    <h2 class="headline headline--serif headline headline--negative headline--medium">
                        <span class="headline__text">Having an Impact</span>
                    </h2>

                    <div class="banner__text">Jordan Kohlmeyer is researching new therapies for tumors</div>

                </div>
            </div>

        </div>

        <div class="slider__teaser">
            <p class="slider__teaser-heading">Having an Impact
                <span aria-hidden="true" class="fas fa-plus"></span>
            </p>
        </div>

    </div>
</div>
  • Content:
    .slider__slide:first-child:focus-within {
      margin-left: 2px; }
    
    .slider {
      flex-wrap: wrap;
      display: flex;
      flex-basis: 100%; }
      @media (min-width: 768px) {
        .slider {
          align-content: stretch;
          align-items: stretch;
          flex-direction: row;
          justify-content: flex-start; } }
      .slider__slide {
        cursor: pointer;
        pointer-events: auto;
        position: relative;
        overflow: hidden;
        color: #fff;
        flex: 1 0 100%; }
        .slider__slide:focus {
          z-index: 2; }
        .slider__slide:first-child:focus-within {
          margin-left: 2px; }
        .slider__slide:last-child:focus-within {
          margin-right: 2px; }
        @media (min-width: 980px) {
          .slider__slide {
            align-self: auto;
            flex: unset;
            order: 0;
            min-height: 500px;
            transition-timing-function: linear;
            transition: 0.8s;
            width: 20%; } }
        @media (min-width: 768px) {
          .slider__slide .banner--medium {
            min-height: 33rem; } }
        .slider__slide .banner__image img {
          display: block;
          width: 100%;
          -o-object-fit: cover;
          object-fit: cover; }
          @media (min-width: 980px) {
            .slider__slide .banner__image img {
              height: 33rem; } }
        @media (min-width: 768px) {
          .slider__slide .banner__text {
            opacity: 0;
            transition: opacity .2s ease-in; } }
        @media (min-width: 768px) {
          .slider__slide .headline {
            opacity: 0;
            transition: opacity .2s linear; } }
        .slider__slide .banner__content {
          opacity: 1;
          padding-top: 2.5rem;
          padding-right: 2.5rem;
          padding-bottom: 2.5rem;
          padding-left: 2.5rem;
          width: 100%; }
          @media (min-width: 768px) {
            .slider__slide .banner__content {
              opacity: 0;
              position: absolute;
              bottom: 0;
              top: unset;
              transition: opacity .2s linear; } }
        @media (min-width: 768px) {
          .slider__slide[aria-expanded="true"] {
            flex-grow: 1;
            transition: 0.3s; } }
        .slider__slide[aria-expanded="true"] .banner__content {
          opacity: 1; }
        .slider__slide[aria-expanded="true"] .headline {
          opacity: 1;
          transition: opacity 1s linear; }
        .slider__slide[aria-expanded="true"] .banner__text {
          opacity: 1;
          transition: opacity 1.5s ease-in; }
        .slider__slide[aria-expanded="true"] .slider__teaser {
          opacity: 0; }
        @media (min-width: 768px) {
          .slider__slide[aria-expanded="true"]:after {
            /*
              position: absolute;
              top: 0;
              right: 0;
              bottom: 0;
              left: 0;
              content: "";
              background: linear-gradient(transparent 1%, transparent 29%, rgba(0, 0, 0, .9));
              */ } }
      .slider__teaser {
        position: absolute;
        z-index: 1;
        bottom: 0;
        width: 100%;
        padding: 1.05rem;
        opacity: 0;
        color: #fff;
        background: rgba(0, 0, 0, 0.75);
        box-shadow: 0 5px 30px 10px rgba(0, 0, 0, 0.3);
        display: flex;
        align-items: center; }
        @media (min-width: 768px) {
          .slider__teaser {
            opacity: 1; } }
      .slider__teaser-heading {
        display: flex;
        margin: 0;
        color: #fff;
        font-size: 1.2rem;
        font-weight: 600;
        font-style: normal;
        line-height: 1;
        padding-right: 2rem;
        display: flex;
        align-items: center; }
        .slider__teaser-heading span {
          padding-left: 0.625rem;
          position: absolute;
          right: 20px; }
          .slider__teaser-heading span.fa-plus:before {
            padding: 0.325rem;
            color: var(--brand-primary);
            border: 1px solid #fff;
            border-radius: 50%;
            font-size: 0.8rem; }
    
  • URL: /components/raw/slider/slider.css
  • Filesystem Path: src/components/slider/slider.css
  • Size: 3.7 KB
  • Content:
    function Slider(element) {
      this.slides = element.getElementsByClassName('slider__slide');
    
      for (let i = 0; i < this.slides.length; i++) {
        this.slides[i].onmouseover = this.slides[i].onfocus = () => {
          this.setActiveSlide(this.slides[i]);
        };
        this.slides[i].addEventListener('keyup', (event) => {
          this.handleKeyEvent(event);
        }, false);
      }
    }
    
    Slider.prototype.setAriaFalse = function() {
      for (let i = 0; i < this.slides.length; i++) {
        let el = this.slides.item(i)
        if (el) {
          el.setAttribute('aria-expanded', 'false');
        }
      }
    }
    
    Slider.prototype.setActiveSlide = function(element) {
      this.setAriaFalse();
      element.setAttribute('aria-expanded', 'true');
    }
    
    Slider.prototype.getActiveSlideIndex = function() {
      for (let i = 0; i < this.slides.length; i++) {
        if (this.slides[i].getAttribute('aria-expanded') === 'true') {
          return i;
        }
      }
    
      return false;
    }
    
    Slider.prototype.handleKeyEvent = function(event) {
      if (event.keyCode === 37) {
        // left - previous
        let index = this.getActiveSlideIndex();
        if (index !== false && index > 0) {
          // @todo Allow looping?
          this.setActiveSlide(this.slides[index-1]);
        }
      } else if (event.keyCode === 39) {
        // right - next
        let index = this.getActiveSlideIndex();
        if (index !== false && index < this.slides.length-1) {
          this.setActiveSlide(this.slides[index+1]);
        }
      }
    }
    
    // Instantiate sliders on the page.
    const sliders = document.getElementsByClassName('slider');
    
    for (let i = 0; i < sliders.length; i++) {
      let slider = new Slider(sliders[i]);
    }
    
  • URL: /components/raw/slider/slider.js
  • Filesystem Path: src/components/slider/slider.js
  • Size: 1.6 KB
  • Content:
    @import '../../assets/scss/variables';
    @import '../../assets/scss/utilities';
    
    .slider__slide:first-child:focus-within {
      margin-left: 2px;
    }
    
    .slider {
      flex-wrap: wrap;
      @include flexbox;
      flex-basis: 100%;
    
      @include breakpoint(sm) {
        align-content: stretch;
        align-items: stretch;
        flex-direction: row;
        justify-content: flex-start;
      }
    
      &__slide {
        cursor: pointer;
        pointer-events: auto;
        position: relative;
        overflow: hidden;
        //min-height: 300px;
        //transition: all 0.4s cubic-bezier(0.61, -0.44, 0.33, 1.39);
        color: $white;
        @include flex(1, 0, 100%);
    
        &:focus {
          z-index: 2;
        }
    
        &:first-child:focus-within {
          margin-left: 2px;
        }
    
        &:last-child:focus-within {
          margin-right: 2px;
        }
    
        @include breakpoint(md) {
          align-self: auto;
          flex: unset;
          order: 0;
          min-height: 500px;
          //transition: all 0.6s ease;
          transition-timing-function: linear;
          transition: 0.8s;
          width: 20%;
        }
    
        // banner overrides
    
        .banner--medium {
          @include breakpoint(sm) {
            min-height: 33rem;
          }
        }
    
        .banner__image img {
          display: block;
          width: 100%;
          -o-object-fit: cover;
          object-fit: cover;
    
          @include breakpoint(md) {
            height: 33rem;
          }
        }
    
        .banner__text {
          @include breakpoint(sm) {
            opacity: 0;
            transition: opacity .2s ease-in;
          }
        }
    
        .headline {
          @include breakpoint(sm) {
            opacity: 0;
            transition: opacity .2s linear;
          }
        }
    
        .banner__content {
          opacity: 1;
    
          @include breakpoint(sm) {
            opacity: 0;
            position: absolute;
            bottom: 0;
            top: unset;
            transition: opacity .2s linear;
          }
    
          @include padding($top: $xlg, $right: $xlg, $bottom: $xlg, $left: $xlg);
          width: 100%;
        }
    
        // Expanded overrides.
        &[aria-expanded="true"] {
          @include breakpoint(sm) {
            flex-grow: 1;
            transition: 0.3s;
          }
    
          .banner__content {
            opacity: 1;
            //transition: opacity 1s linear;
          }
    
          .headline {
            opacity: 1;
            transition: opacity 1s linear;
          }
    
          .banner__text {
            opacity: 1;
            transition: opacity 1.5s ease-in;
          }
    
          .slider__teaser {
            opacity: 0;
          }
    
          &:after {
            @include breakpoint(sm) {
              /*
              position: absolute;
              top: 0;
              right: 0;
              bottom: 0;
              left: 0;
              content: "";
              background: linear-gradient(transparent 1%, transparent 29%, rgba(0, 0, 0, .9));
              */
            }
          }
        }
      }
    
      &__teaser {
        position: absolute;
        z-index: 1;
        bottom: 0;
        width: 100%;
        padding: $md;
        //transition: opacity .4s linear;
        opacity: 0;
    
        @include breakpoint(sm) {
          opacity: 1;
        }
    
        color: $white;
        background: rgba(0, 0, 0, 0.75);
        box-shadow: 0 5px 30px 10px rgba(0, 0, 0, 0.3);
        @include center(vertical);
      }
    
      &__teaser-heading {
        display: flex;
        margin: 0;
        color: $white;
        font-size: $h6-font-size;
        font-weight: $font-weight-medium-bold;
        font-style: normal;
        line-height: 1;
        padding-right: 2rem;
        @include center(vertical);
    
        span {
          padding-left: $sm;
          position: absolute;
          right: 20px;
    
          &.fa-plus:before {
            padding: $xsm;
            color: $primary;
            border: 1px solid $white;
            border-radius: 50%;
            font-size: $small-font-size;
          }
        }
      }
    }
    
  • URL: /components/raw/slider/slider.scss
  • Filesystem Path: src/components/slider/slider.scss
  • Size: 3.6 KB