skip to Main Content

I am trying to add a feature to show an alternative product picture when the cursor hovers over the product image in a collection view.

Whenever I view the page with the code below, the product images have shifted to the bottom of the container and also cover the Title/Price that was below them.

What can I correct to keep the pictures in their original alignment and have only the hover effect work?

Thank you!

Here is what I currently have in product-card-grid.liquid —

<div id="{{ wrapper_id }}" class="grid-view-item__image-wrapper js">
    <div style="padding-top:{% unless product.featured_image == blank %}{{ 1 | divided_by: product.featured_image.aspect_ratio | times: 100}}%{% else %}100%{% endunless %};">
     <div class="reveal">
      <img id="{{ img_id }}"
            class="grid-view-item__image lazyload"
            src="{{ product.featured_image | img_url: '300x300' }}"
            data-src="{{ img_url }}"
            data-widths="[180, 360, 540, 720, 900, 1080, 1296, 1512, 1728, 2048]"
            data-aspectratio="{{ product.featured_image.aspect_ratio }}"
            data-sizes="auto"
            alt="">
      <img id="{{img_id}}"
           class="hidden" 
           src="{{ product.images.last }}"
           data-src="{{ img_url }} "
           data-widths="[180, 360, 540, 720, 900, 1080, 1296, 1512, 1728, 2048]"
           data-aspectratio="{{ product.featured_image.aspect_ratio }}"
           data-sizes="auto"
           alt="{{ product.images.last.alt | escape }}">
      </div>
    </div>
  </div>

The css for “Reveal” is below:

  /* ===============================================
// Reveal module
// =============================================== */

.reveal .hidden { display: block !important; visibility: visible !important;}
.product:hover .reveal img { opacity: 1; }
.reveal { position: relative; }
.reveal .hidden { 
  position: absolute; 
  z-index: -1;
  top: 0; 
  width: 100%; 
  height: 100%;  
  opacity: 0;
  -webkit-transition: opacity 0.3s ease-in-out;
  -moz-transition: opacity 0.3s ease-in-out;
  -o-transition: opacity 0.3s ease-in-out;
  transition: opacity 0.3s ease-in-out;  
}
.reveal:hover .hidden { 
  z-index: 100000;
  opacity: 1;    
}
.reveal .caption {
  position: absolute;
  top: 0;  
  display: table;
  width: 100%;
  height: 100%;
  background-color: white; /* fallback for IE8 */
  background-color: rgba(255, 255, 255, 0.7);
  font: 13px/1.6 sans-serif;
  text-transform: uppercase;
  color: #333;
  letter-spacing: 1px;
  text-align: center;
  text-rendering: optimizeLegibility;
}
.reveal .hidden .caption .centered {
  display: table-cell;
  vertical-align: middle;
}

@media (min-width: 480px) and (max-width: 979px) {
  .reveal .caption { 
    font-size: 11px; 
  }
}

2

Answers


  1. Chosen as BEST ANSWER

    Got it to work with the following

    In the CSS, I had the @media (hover:hover){} so that users do not have to double click an image on mobile to go to the product page.

    CSS:

    /* ===============================================
    // Reveal module
    // =============================================== */
    @media (hover:hover) {
    .has-secondary.grid-view-item__link img.secondary{
     display:none;
    }
    }
    
    @media (hover:hover) {
    .has-secondary.grid-view-item__link:hover img.secondary{
     display:block;
    }
    }
    
    @media (hover:hover) {
    .has-secondary.grid-view-item__link:hover img.grid-view-item__image{
     display:none;
    }
    }
    
    @media screen and (min-width:767px){
    .has-secondary.grid-view-item__link img.secondary{
     display:none;
    }
    
    .has-secondary.grid-view-item__link:hover img.secondary{
     display:block;
    }
    
    .has-secondary.grid-view-item__link:hover img.grid-view-item__image{
     display:none;
    }
    }
    
    @media screen and (max-width:767px){
    .has-secondary.grid-view-item__link img.secondary{
     display:none;
    }
    }
    

    Changed product-card-grid.liquid HTML/Liquid to the following:

    {% unless grid_image_width %}
      {%- assign grid_image_width = '600x600' -%}
    {% endunless %}
    <div class="grid-view-item{% unless product.available %} product-price--sold-out grid-view-item--sold-out{% endunless %}">
      <a class="grid-view-item__link {% if product.images.size > 1 %} has-secondary{% endif %}" href="{{ product.url | within: collection }}">
        <img class="grid-view-item__image" src="{{ product.featured_image.src | img_url: grid_image_width }}" alt="{{ product.featured_image.alt }}">
        {% if product.images.size > 1 %}
         <img class="secondary" src="{{ product.images.last | img_url: grid_image_width }}" alt="{{ product.images.last.alt | escape }}">
        {% endif %}
      </a>
    </div>
    
    <div class="h4 grid-view-item__title">
         <a href="{{ product.url | within: collection }}"> {{ product.title }} </a>
    </div>   
    {% if section.settings.show_vendor %}
          <div class="grid-view-item__vendor">{{ product.vendor }}</div>
        {% endif %}
     <div class="grid-view-item__meta">
       <a href="{{ product.url | within: collection }}"> {% include 'product-price', variant: product %} </a>
        </div> 
    

  2. There’s a lot going on in your CSS, but if I understand the sitaution correctly you want to achieve an effect like the one in this Codepen, right?

    In your CSS, absolutely position two images inside of a div (with top: 0px and left: 0px) and change the opacity of the top image in the stack by hovering on the parent.

    HTML:

    <div class='reveal'>
      <img src='image_src' class='bottom'>
      <img src='image_src' class='top'>
    </div>
    

    CSS:

    .top, .bottom {
      position: absolute;
      opacity: 1;
      top: 0px;
      left: 0px;
    }
    
    .frame:hover .top {
      opacity: 0;
    }
    

    EDIT: Implementation w/ grid, as requested.

    HTML:

    <div class='grid'>
        <div class='reveal'>
          <img src='image_src' class='bottom'>
          <img src='image_src' class='top'>
        </div>
        <div class='reveal'>
          <img src='image_src' class='bottom'>
          <img src='image_src' class='top'>
        </div>
    </div>
    

    CSS:

    .grid {
      display: flex;
      flex-wrap: wrap; /*makes the grid "responsive"*/
    }
    
    .reveal {
      display: flex;
      flex: 1 1 200px; /*last value must be picture width*/
      height:200px; /* picture height*/
      margin: 20px; /*aesthetic only*/
      position: relative;
    }
    
    .top, .bottom {
      position: absolute;
      opacity: 1;
      top: 0px;
      left: 50%; /*centers pictures inside flex children (.reveal divs)*/
      transform: translate(-50%, 0); /*see above*/
    }
    
    .reveal:hover .top {
      opacity: 0;
    }
    

    Demo on Codepen

    The above example uses flexbox to create a simple grid which will work with the (slightly modified) .reveal divs from my original post. If you’re unfamiliar with flexbox syntax, there’s an awesome free video course from Wes Bos that I highly recommend.

    P.S. Note that the grid will only work “out of the box” if the images have a set pixel width, although you could easily support different images sizes with a little media query magic.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search