Search code examples
jekyllcarouselgithub-pagesliquid

Add links to Jekyll slider/carousel for github-pages


I am using the Jekyll codex slider on my jekyll-based github pages site based on minimal mistakes theme. It works fine, but I would like to add links for each image in the slider. The links to go specific posts.

I added url to the data file. With references to post names used in full url path:

carousels:
  - images: 
    - image: /assets/images/image-1.jpg
      url: post-name-1
    - image: /assets/images/image-2.jpg
      url: post-name-2
    - image: /assets/images/image-3.jpg
      url: post-name-3

I'm not sure how to get those links into the carousel _include. I've tried adding a href that prepends with the site.baseurl, a separate for loop and various other approaches, but I feel like I'm just not seeing the right way. And I think it's probably simple, but I don't have the experience. Any advice to put me on the right path appreciated. Thanks.

{% assign letterstring = "a,b,c,d,e,f,g,h,i,j,k,l,m,n" %}
{% assign letters = letterstring | split: ',' %}
{% assign number = include.number | minus: 1 %}
<div class="carousel__holder">
    <div id="carousel{{ number }}" class="carousel">
        {% for item in page.carousels[number].images %}
          <input class="carousel__activator" type="radio" name="carousel{{ number }}" id="{{ number }}{{ letters[forloop.index0] }}" {% if forloop.first %}checked="checked"{% endif %} />
        {% endfor %}
        {% for item in page.carousels[number].images %}
          {% if forloop.index == forloop.length %}
            {% assign nextindex = 0 %}
          {% else %}
            {% assign nextindex = forloop.index0 | plus: 1 %}
          {% endif %}
          {% assign nextletter = letters[nextindex] %}
          {% if forloop.index0 == 0 %}
            {% assign previndex = forloop.length | minus: 1 %}
          {% else %}
            {% assign previndex = forloop.index0 | minus: 1 %}
          {% endif %}
          {% assign prevletter = letters[previndex] %}
          <div class="carousel__controls">
              <label class="carousel__control carousel__control--backward" for="{{ number }}{{ prevletter }}"></label>
              <label class="carousel__control carousel__control--forward" for="{{ number }}{{ nextletter }}"></label>
          </div>
        {% endfor %}
        <div class="carousel__track">
          <ul>
            {% for item in page.carousels[number].images %}
            <li class="carousel__slide" style="background-image: url('{{ item.image }}');"></li>
            {% endfor %}
          </ul>
        </div>
        <div class="carousel__indicators">
            {% for item in page.carousels[number].images %}
              <label class="carousel__indicator" for="{{ number }}{{ letters[forloop.index0] }}"></label>
            {% endfor %}
        </div>
    </div>
</div>

<style>
.carousel__holder {width: 100%; position: relative; padding-bottom: {{ include.height }}{{ include.unit }}; margin: 1rem 0 1rem;}
.carousel {
  height: 100%;
  width: 100%;
  overflow: hidden;
  text-align: center;
  position: absolute;
  padding: 0;
}
.carousel__controls,
.carousel__activator {
  display: none;
}
{% for item in page.carousels[number].images %}
.carousel__activator:nth-of-type({{ forloop.index }}):checked ~ .carousel__track {
  -webkit-transform: translateX(-{{ forloop.index0 }}00%);
          transform: translateX(-{{ forloop.index0 }}00%);
}
.carousel__activator:nth-of-type({{ forloop.index }}):checked ~ .carousel__slide:nth-of-type({{ forloop.index }}) {
  transition: opacity 0.5s, -webkit-transform 0.5s;
  transition: opacity 0.5s, transform 0.5s;
  transition: opacity 0.5s, transform 0.5s, -webkit-transform 0.5s;
  top: 0;
  left: 0;
  right: 0;
  opacity: 1;
  -webkit-transform: scale(1);
          transform: scale(1);
}
.carousel__activator:nth-of-type({{ forloop.index }}):checked ~ .carousel__controls:nth-of-type({{ forloop.index }}) {
  display: block;
  opacity: 1;
}
.carousel__activator:nth-of-type({{ forloop.index }}):checked ~ .carousel__indicators .carousel__indicator:nth-of-type({{ forloop.index }}) {
  opacity: 1;
}
{% endfor %}

.carousel__control {
  height: 30px;
  width: 30px;
  margin-top: -15px;
  top: 50%;
  position: absolute;
  display: block;
  cursor: pointer;
  border-width: 5px 5px 0 0;
  border-style: solid;
  border-color: #fafafa;
  opacity: 0.35;
  opacity: 1;
  outline: 0;
  z-index: 3;
}
.carousel__control:hover {
  opacity: 1;
}
.carousel__control--backward {
  left: 20px;
  -webkit-transform: rotate(-135deg);
          transform: rotate(-135deg);
}
.carousel__control--forward {
  right: 20px;
  -webkit-transform: rotate(45deg);
          transform: rotate(45deg);
}
.carousel__indicators {
  position: absolute;
  bottom: 20px;
  width: 100%;
  text-align: center;
}
.carousel__indicator {
  height: 15px;
  width: 15px;
  border-radius: 100%;
  display: inline-block;
  z-index: 2;
  cursor: pointer;
  opacity: 0.35;
  margin: 0 2.5px 0 2.5px;
}
.carousel__indicator:hover {
  opacity: 0.75;
}
.carousel__track {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  padding: 0;
  margin: 0;
  transition: -webkit-transform 0.5s ease 0s;
  transition: transform 0.5s ease 0s;
  transition: transform 0.5s ease 0s, -webkit-transform 0.5s ease 0s;
}
.carousel__track .carousel__slide {
  display: block;
  top: 0;
  left: 0;
  right: 0;
  opacity: 1;
}
{% for item in page.carousels[number].images %}
.carousel__track .carousel__slide:nth-of-type({{ forloop.index }}) {
  -webkit-transform: translateX({{ forloop.index0 }}00%);
          transform: translateX({{ forloop.index0 }}00%);
}
{% endfor %}

.carousel--scale .carousel__slide {
  -webkit-transform: scale(0);
          transform: scale(0);
}
.carousel__slide {
  height: 100%;
  position: absolute;
  opacity: 0;
  overflow: hidden;
}
.carousel__slide .overlay {height: 100%;}
.carousel--thumb .carousel__indicator {
  height: 30px;
  width: 30px;
}
.carousel__indicator {
  background-color: #fafafa;
}
{% for item in page.carousels[number].images %}
.carousel__slide:nth-of-type({{ forloop.index }}),
.carousel--thumb .carousel__indicators .carousel__indicator:nth-of-type({{ forloop.index }}) {
  background-size: cover;
  background-position: center;
}
{% endfor %}
</style>

<script>
  function isVisible(el) {
        while (el) {
            if (el === document) {
                return true;
            }

            var $style = window.getComputedStyle(el, null);

            if (!el) {
                return false;
            } else if (!$style) {
                return false;
            } else if ($style.display === 'none') {
                return false;
            } else if ($style.visibility === 'hidden') {
                return false;
            } else if (+$style.opacity === 0) {
                return false;
            } else if (($style.display === 'block' || $style.display === 'inline-block') &&
                $style.height === '0px' && $style.overflow === 'hidden') {
                return false;
            } else {
                return $style.position === 'fixed' || isVisible(el.parentNode);
            }
        }
  }
  {% if include.duration %}
  setInterval(function(){
    var j=0;
    var elements = document.querySelectorAll('#carousel{{ number}} .carousel__control--forward');
    for(i=(elements.length - 1);i>-1;i--) {
      if(isVisible(elements[i])) j=i;
    }
    elements[j].click();
  },{{ include.duration }}000);
  {% endif %}
</script>

Update Dec 14 2022

I added relative URL and got a link to work for the first image by wrapping the <li> with the href:

    <ul>
      {% for item in site.data.carousels.carousels[number].images %}
      <a href="{{ item.url | relative_url }}">
      <li class="carousel__slide" style="background-image: url('{{ item.image }}');"></li>
      </a>
     {% endfor %}
   </ul>

But the next images don't display. Adding the href before or after the <li> doesn't work at all.

    <ul>
      {% for item in site.data.carousels.carousels[number].images %}
      <li class="carousel__slide" style="background-image: url('{{ item.image }}');"></li>
      <a href="{{ item.url | relative_url }}">Link text</a>
     {% endfor %}
   </ul>

Solution

  • When you include a carousel,

    {% include carousel.html height="50" unit="%" duration="7" number="1" %}
    

    the number parameter in the code is the index (the code substracts 1):

    {% for item in page.carousels[number].images %}
        {{ item.image }}
        ...
    

    If this is your frontmatter,

    carousels:
    - images: 
      - image: /assets/images/image-1.jpg
        url: post-name-1
      - image: /assets/images/image-2.jpg
        url: post-name-2
      - image: /assets/images/image-3.jpg
        url: post-name-3
    

    you can access the image by using item.url the same way you access the image.

    Text link on the image

    ...
        <div class="carousel__track">
          <ul>
            {% for item in page.carousels[number].images %}
              <li class="carousel__slide" style="background-image: url('{{ item.image }}');"><a href="{{ item.url }}">{{ item.url }}</a></li>
            {% endfor %}
          </ul>
        </div>
    ...
    

    You can use absolute_url or relative URL filters according to the docs.

    Link on the complete image/slide

    To make the entire <li> an image, try this (used inline-styles for simplicity - syntax and CSS from this post):

        <div class="carousel__track">
          <ul>
            {% for item in page.carousels[number].images %}
              <li class="carousel__slide" style="background-image: url('{{ item.image }}');">
                <a style="text-decoration:none;display:block;width:100%;height:100%;" href="{{ item.url }}"></a>
              </li>
            {% endfor %}
          </ul>
        </div>