Search code examples
jquerycsslightbox

Lightbox not opening due to smooth scroll?


I'm trying to implement a CSS only lightbox effect for some certificates on my personal site. Unfortunately, whenever I click the image that I would like to expand, it either scrolls to the top of the page, or just a little bit down - instead of targeting the full size image (I believe this is due to the smooth scrolling logic confusing the hashmark in the image target with the hashmark in the page target). I can only access the expanded image by manually typing the address in the browser. Any suggestions??

Here is the site link.

enter image description here

enter image description here

    <div class="background-certs" id="certificates">  
  <div class="title-box">
    <h3 class="h3-web">{ certificates }</h3>
    <h4 class="h4-web">I enjoy learning</h4>
  </div>    

  <div class="cert-container">
    <a href="#cert-item-1" class="button-new">
      <div class="box1 grid-sub">
          <%= image_tag "firehose.jpg", class: "full-width-cert" %>
      </div>
      </a>
    <h4 class="h4-subtitle">software engineering bootcamp</h4>
    <p class="cert-subtitle">Dec. 2017 - Oct. 2018</p> 
  </div>

  <div class="cert-container">
    <a href="#cert-item-2" class="button-new">
      <div class="box1 grid-sub">
        <%= image_tag "udemy-js.jpg", class: "full-width-cert" %>
      </div>
    </a>  
    <h4 class="h4-subtitle">JavaScript: the weird parts</h4>
    <p class="cert-subtitle">Nov. 2018</p> 
  </div>

    <br class="clear" />

    <div class="cert-container">
      <a href="#cert-item-3" class="button-new">
        <div class="box1 grid-sub">
          <%= image_tag "udemy-algos.jpg", class: "full-width-cert" %>
        </div>
      </a> 
      <h4 class="h4-subtitle">algorithms + data structures</h4>
      <p class="cert-subtitle">Dec. 2018</p> 
    </div>

    <div class="cert-container">
      <a href="#cert-item-4" class="button-new">
        <div class="box1 grid-sub">
          <%= image_tag "udemy-shopify.jpg", class: "full-width-cert" %>
        </div>
      </a>
      <h4 class="h4-subtitle">shopify themes from scratch</h4>
      <p class="cert-subtitle">Feb. 2019</p> 
    </div>


    <div class="certificate-lightboxes">

      <div class="cert-lightbox" id="cert-item-1">
        <div class="cert-lightbox__content">
          <a href="#certificates" class="close"></a>
          <%= image_tag "firehose.jpg", class: "full-width-cert" %>
        </div>
      </div>

      <div class="cert-lightbox" id="cert-item-2">
        <div class="cert-lightbox__content">
          <a href="#certificates" class="close"></a>
          <%= image_tag "udemy-js.jpg", class: "full-width-cert" %>
        </div>
      </div>

      <div class="cert-lightbox" id="cert-item-3">
        <div class="cert-lightbox__content">
        <a href="#certificates" class="close"></a>
          <%= image_tag "udemy-algos.jpg", class: "full-width-cert" %>
        </div>
      </div>

      <div class="cert-lightbox" id="cert-item-4">
        <div class="cert-lightbox__content">
          <a href="#certificates" class="close"></a>
          <%= image_tag "udemy-shopify.jpg", class: "full-width-cert" %>
        </div>
      </div>

    </div>


    <div class="bottom-line"></div>
  </div> 
/** LIGHTBOX MARKUP **/

.cert-lightbox {
  display: flex;
  position: fixed;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  background: black;
  align-items: center;
  justify-content: center;
  transform: scale(0, 0);
  transition: transform ease-in-out 100ms;
}

.cert-lightbox:target {
  transform: scale(1, 1) !important;
  display: flex;
  z-index: 900;
}

.cert-lightbox__content {
  width: 65%;
  position: relative;
}

.close {
  position: absolute;
  width: 2em;
  height: 2em;
  background: red;
  top: -1em;
  right: -1em;
  border-radius: 50%;
  text-decoration: none;
  display: flex;
  align-items: center;
  justify-content: center;
}

.close::after {
  content: "X";
  color: white;
  font-weight: 700;
}

smooth scroll in application.html.erb

<script type="text/javascript">
var $root = $('html, body');

$('a[href^="#"]').click(function () {
$root.animate({
    scrollTop: $( $.attr(this, 'href') ).offset().top
}, 400);

return false;
  });
  </script>

smooth scroll in scroll.js

 function scrollToHash(event) {
// On-page links
if (
  location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') 
  && 
  location.hostname == this.hostname
) {
  // Figure out element to scroll to
  var target = $(this.hash);
  target = target.length ? target : $('[name=' + this.hash.slice(1) + ']');
  // Does a scroll target exist?
  if (target.length) {
    // Only prevent default if animation is actually gonna happen
    event.preventDefault();
    $('html, body').animate({
      scrollTop: target.offset().top
    }, 1000, function() {
      // Callback after animation
      // Must change focus!
      var $target = $(target);
      $target.focus();
      if ($target.is(":focus")) { // Checking if the target was focused
        return false;
      } else {
        $target.attr('tabindex','-1'); // Adding tabindex for elements not focusable
        $target.focus(); // Set focus again
      };
    });
  }
}
};

  // Select all links with hashes
 $('a[href*="#"]')
  // Remove links that don't actually link to anything
   .not('[href="#"]')
  .not('[href="#0"]')
  .click(scrollToHash);

Solution

  • Avoiding attaching smooth scroll listeners to links with an attribute

    As a slight improvement over adding multiple .not calls like .not('[href="#cert-item-1"]') to your smooth scroll initialization, you could add a custom HTML attribute data-no-smooth-scroll to each of your lightbox links (about data- attributes):

    <div class="cert-container">
      <a href="#cert-item-1" data-no-smooth-scroll class="button-new"> <!-- added on this line -->
        <div class="box1 grid-sub">
          <%= image_tag "firehose.jpg", class: "full-width-cert" %>
        </div>
      </a>
      <h4 class="h4-subtitle">software engineering bootcamp</h4>
      <p class="cert-subtitle">Dec. 2017 - Oct. 2018</p> 
    </div>
    
    <!-- also add the attribute within the `a` for #cert-item-2, etc. -->
    

    Then only a single .not is needed in the JavaScript:

    // Select all links with hashes
    $('a[href*="#"]')
      // Remove links that don't actually link to anything
      .not('[href="#"]')
      .not('[href="#0"]')
      .not('[data-no-smooth-scroll]') // this line was added
      .click(scrollToHash);
    

    The selector [data-no-smooth-scroll] is a Has Attribute selector.

    Removing smooth scroll listeners when setting up the lightbox

    Alternatively, you could change your lightbox initialization code to call .off('click') (assuming that it uses jQuery – you didn’t show that code). This will remove any existing click event listeners from the selected links before attaching the new click event listeners that open a lightbox.

    This would be cleaner in some ways, but it would introduce a requirement that the lightboxes be initialized after the smooth scrolling. Also, if you ever added another global click handler such as Google Analytics, it would remove that handler too. So I worry that this solution would be hard to keep working as the code is changed in the future.