Hi everyone,
It’s been a while, but I have a Safari problem that I believe is occurring on both desktop and iOS versions of Safari.
On this page here (https://ashanderie.com/products/sweaters), I’ve created a very hacky way to force Shopify to create pseudo-element subheaders such as “Quarter Zips”. This effect visually works and all label elements are clickable on Windows Edge, IE10, Firefox, Chrome, and Android Chrome. On OSX and iPhone Safari, almost none of the label elements are clickable therefore breaking that navigation.
I know the code I’m using to create this visual effect is (honestly) horrible, but it was the only way to force that due to the fact that the label swatches shown on that page are dynamically created by inline javascript.
Here’s the relevant product page code and SCSS styling below. I believe the real solution (if there is one) has to mostly to do with the SCSS since that’s how I’ve created my current solution in the first place.
SCSS Styling (just the part that affects this specific product page)
// Sweaters
.sweaters {
.charcoal-quarter-zip, .navy-quarter-zip, .blue-ink-quarter-zip, .midnight-v-neck, .navy-v-neck,
.blue-ink-crew-neck, .smoke-crew-neck {
label {
min-width: 65px !important;
min-height: 45px;
background-position: center !important;
}
.tooltip {
display: none;
}
}
.charcoal-quarter-zip {
&:before {
background: white;
content: "Quarter Zips";
display: block;
clear: both;
margin-top: -30px;
padding-bottom: 10px;
}
.tooltip {
left: -15px;
margin-bottom: -15px;
}
}
.navy-quarter-zip {
.tooltip {
left: 65px;
}
}
.blue-ink-quarter-zip {
.tooltip {
left: 145px;
}
}
.midnight-v-neck {
&:before {
content: "V Necks";
display: block;
clear: both;
margin-top: 55px;
padding-bottom: 10px;
}
.tooltip {
left: -15px;
margin-bottom: -15px;
}
}
.navy-v-neck {
&:after {
padding-bottom: 5px;
}
.tooltip {
left: 65px;
}
}
.blue-ink-crew-neck {
&:before {
content: "Crew Necks";
display: block;
clear: both;
margin-top: 55px;
padding-bottom: 10px;
}
.tooltip {
left: -15px;
margin-bottom: -15px;
}
}
.smoke-crew-neck {
.tooltip {
left: 65px;
}
// To force correct padding for size labels
label {
margin-bottom: 10px;
}
}
.swatch-element {
// Overwrite default styles
float: inherit;
margin: 0;
&.xs, &.s, &.m, &.l, &.xl, &.xxl {
float: left;
margin-bottom: 10px;
}
label {
margin-right: 15px;
}
}
}
HTML Liquid Code (basically HTML)
<!-- /templates/product.liquid -->
{% comment %}
Rich snippets (itemscope, itemtype, etc.) for products are a theme requirement,
and allow search engines to easily understand what the content is.
For more information on these Scheme.org tags, visit:
- http://schema.org/docs/gs.html
{% endcomment %}
{{'owl.carousel.css' | asset_url | stylesheet_tag }}
{{'owl.theme.css' | asset_url | stylesheet_tag }}
{{'owl.carousel.min.js' | asset_url | script_tag }}
<div class="product-wrapper second-batch in-stock">
<div class="image-tint"></div>
<main class="wrapper" role="main">
<div itemscope itemtype="http://schema.org/Product">
<meta itemprop="url" content="{{ shop.url }}{{ product.url }}">
<meta itemprop="image" content="{{ product.featured_image.src | img_url: 'grande' }}">
{% comment %}
Get first variant, or deep linked one
{% endcomment %}
{% assign current_variant = product.selected_or_first_available_variant %}
<div class="grid product-single">
<div class="grid__item product-description-wrapper small--show medium--show large--hide">
<div class="product-description-snippet">
<div class="product-title-wrapper">
<!-- <p class="premium-product-title">Classic Collection</p> -->
<h1 class="product-name" itemprop="name">Long Sleeve Shirt</h1>
<h3 class="product-variant-title">
<span class="visually-hidden">{{ 'products.general.regular_price' | t }}</span>
<span class="variant-title"></span> -
<span class="product-price" itemprop="price">{{ current_variant.price | money }}</span>
<span class="compare-price"></span>
</h3>
<a href="#testimonials2" class="">
<div class="rating abtest">
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
<span class="star-text">(621 reviews)</span>
</div>
</a>
</div>
</div>
</div>
<div class="grid__item large--seven-twelfths product-image">
<section class="product-image-wrapper">
<div class="image-parent" id="ProductPhoto">
{% assign featured_image = product.selected_or_first_available_variant.featured_image | default: product.featured_image %}
<img src="{{ featured_image | img_url: 'master' }}" alt="{{ featured_image.alt | escape }}" id="ProductPhotoImg">
</div>
</section>
{% if product.images.size > 1 %}
<div class="b-product-thumbs">
<div id="product_carousel">
</div>
<!-- /#product-carousel -->
</div>
<!-- /.b-product-thumbs -->
<div class="b-product-image hide product_thumbs">
{% for image in product.images %}
<div class="b-product-thumbs_item jsThumb" data-variant="{{image.alt}}" style="display:none;">
<a href="{{image | img_url: '1024x1024'}}" class="b-product-thumbs__link" data-grande="{{image | img_url: 'grande'}}">
<img src="{{image | img_url: 'grande'}}" alt="{{product.title}}" class="img">
</a>
</div>
<!-- /.b-product-thumbs b-product-thumbs_item -->
{% endfor %}
</div>
{% endif %}
</div>
<div class="grid__item large--five-twelfths">
<div class="product-content">
<div class="product-description-wrapper" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
<div class="product-description-snippet small--hide medium--hide">
<div class="product-title-wrapper">
<!-- <p class="premium-product-title">Classic Collection</p> -->
<h1 class="product-name" itemprop="name">Long Sleeve Shirt</h1>
<h3 class="product-variant-title">
<span class="visually-hidden">{{ 'products.general.regular_price' | t }}</span>
<span class="variant-title"></span> -
<span class="product-price" itemprop="price">{{ current_variant.price | money }}</span>
<span class="compare-price"></span>
</h3>
<a href="#testimonials2" class="">
<div class="rating abtest">
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
<span class="star-text">(621 reviews)</span>
</div>
</a>
<hr class="variant-hr">
</div>
<p class="product-description">It's an everyday casual button down that can be worn at work, play, or wherever.</p>
</div>
<meta itemprop="priceCurrency" content="{{ shop.currency }}">
<link itemprop="availability" href="http://schema.org/{% if product.available %}InStock{% else %}OutOfStock{% endif %}">
{% comment %}
ID addToCartForm is a selector for the ajax cart plugin
{% endcomment %}
<form action="/cart/add" method="post" enctype="multipart/form-data" id="AddToCartForm" class="form-vertical">
{% comment %}
Add product variants as a dropdown.
- By default, each variant (or combination of variants) will display as its own <option>
- To separate these into multiple steps, which we suggest, use option_selection.js (see below)
You can leverage jQuery to add a callback on page load and each time the select element changes:
- Include option_selection.js (as seen at the bottom of this file)
- This allows you to use JavaScript anytime the variant dropdown changes
- This also separates out your variant options (ie. size, color, etc.) to separate select elements
For more information on products with multiple options, visit:
- http://docs.shopify.com/support/your-website/themes/can-i-make-my-theme-use-products-with-multiple-options#update-product-liquid
{% endcomment %}
<select name="id" id="productSelect" class="product-single__variants">
{% for variant in product.variants %}
{% if variant.available %}
{% comment %}
Note: if you use option_selection.js, your <select> tag will be overwritten, meaning what you have inside <option> will not reflect what you coded below.
{% endcomment %}
<option {% if variant == product.selected_or_first_available_variant %} selected="selected" {% endif %} value="{{ variant.id }}">{{ variant.title }} - {{ variant.price | money_with_currency }}</option>
{% else %}
<option disabled="disabled">
{{ variant.title }} - {{ 'products.product.sold_out' | t }}
</option>
{% endif %}
{% endfor %}
</select>
<!-- {% if product.compare_at_price_max > product.price %}
<span class="visually-hidden">{{ 'products.general.sale_price' | t }}</span>
<p id="ComparePrice">
{{ 'products.product.compare_at' | t }} {{ current_variant.compare_at_price | money }}
</p>
{% endif %} -->
{% if product.available and product.variants.size > 1 %}
{% for option in product.options %}
{% include 'swatch' with option %}
{% endfor %}
{% endif %}
<!-- Quantity selector -->
<!-- <label for="Quantity" class="quantity-selector">{{ 'products.product.quantity' | t }}</label>
<input type="number" id="Quantity" name="quantity" value="1" min="1" class="quantity-selector"> -->
<div class="grid main-buttons">
<div class="grid__item">
<button type="submit" name="add" id="AddToCart" class="btn btn--full buy-button" onClick="ga('send', 'event', 'Funnel Tracking', 'Click' , 'Add to Cart' );">
<span id="AddToCartText">{{ 'products.product.add_to_cart' | t }}</span>
</button>
</div>
<div class="grid__item bundle-modal-button">
<a href="#openModal3">
<p class="modal-button">Get <span class="bundle-code">$30 off</span> when you bundle ►</p>
</a>
</div>
<div id="shopmessage-checkbox"></div>
<!-- <div class="grid__item">
<p class="no-promo-code">No other promo codes can be used on this sale item.</p>
</div> -->
</div>
<div class="grid sub-buttons">
<div class="grid__item one-third">
<img src="https://cdn.shopify.com/s/files/1/0932/9384/files/free-shipping.png?17636541993369187108" alt="Free US Shipping and Returns">
</div>
<div class="grid__item one-third">
<a href="#openModal">
<img src="https://cdn.shopify.com/s/files/1/1401/9421/files/find-my-fit-button.jpg?6589481884120741418" alt="Find My Fit">
</a>
</div>
<div class="grid__item one-third">
<a href="#openModal2">
<img src="https://cdn.shopify.com/s/files/1/1401/9421/files/questions-button.jpg?6589481884120741418" alt="Questions? Ask Us">
</a>
</div>
</div>
<div class="extra-info">
<!-- <img src="https://cdn.shopify.com/s/files/1/0932/9384/files/product-page_2fde5334-5008-4f7f-85d5-21a8bb85285f.jpg?6854762801031602409" alt="Cyber Monday Sale - Save 20% Off!">
<br> -->
<!-- <hr class="extra-info-hr"> -->
<br>
<h3 class="extra-info-title">Product Details</h3>
<div class="small--show medium--show large--hide">
<p class="product-description">It's an everyday casual button down that can be worn at work, play, or wherever.</p>
</div>
<div class="grid">
<div class="grid__item one-half">
<ul>
<li>100% pre-shrunk cotton</li>
<li>Designed to wear untucked</li>
</ul>
</div>
<div class="grid__item one-half">
<ul>
<li>Incredibly soft feeling</li>
<li>Refined collar</li>
</ul>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% comment %}
To take advantage of a callback on the select dropdown, add option_selection.js
and customize the JS in timber.productPage as needed.
Currently, timber.productPage does the following:
- Hides your <select> tag from above
- Breaks out the product variants into separate product options, if more than one exists
- Generates a <select> tag for each product option
- Enables/disables elements based on variant availability
Callback notes:
- Keep the callback available to the global scope (window.selectCallback) so that advanced
addons can override it.
* E.g. multiple currencies http://docs.shopify.com/manual/configuration/store-customization/currencies-and-translations/currencies/how-to-toggle-between-two-currencies
{% endcomment %}
{{ 'option_selection.js' | shopify_asset_url | script_tag }}
<script>
Shopify.Image.preload({{ product.images | json }}, '1024x1024');
var selectCallback = function(variant, selector) {
// BEGIN SWATCHES
if (variant) {
var form = jQuery('#' + selector.domIdPrefix).closest('form');
for (var i=0,length=variant.options.length; i<length; i++) {
var radioButton = form.find('.swatch[data-option-index="' + i + '"] :radio[value="' + variant.options[i] +'"]');
if (radioButton.size()) {
radioButton.get(0).checked = true;
}
}
}
// END SWATCHES
timber.productPage({
money_format: "{{ shop.money_format }}",
variant: variant,
selector: selector
});
if (variant && variant.featured_image) {
var originalImage = $(".image-parent img");
var newImage = variant.featured_image;
var element = originalImage[0];
Shopify.Image.switchImage(newImage, element, function (newImageSizedSrc, newImage, element) {
$(element).parents('a').attr('href', newImageSizedSrc);
$(element).attr('src', newImageSizedSrc);
});
}
};
jQuery(function($) {
new Shopify.OptionSelectors('productSelect', {
product: {{ product | json }},
onVariantSelected: selectCallback,
enableHistoryState: true
});
// Add label if only one product option and it isn't 'Title'. Could be 'Size'.
{% if product.options.size == 1 and product.options.first != 'Title' %}
$('.selector-wrapper:eq(0)').prepend('<label for="productSelect-option-0">{{ product.options.first | escape }}</label>');
{% endif %}
// Hide selectors if we only have 1 variant and its title contains 'Default'.
{% if product.variants.size == 1 and product.variants.first.title contains 'Default' %}
$('.selector-wrapper').hide();
{% endif %}
});
jQuery(document).ready(function($) {
var images_wrapper = $("#product_carousel");
var all_images = $('.product_thumbs .jsThumb');
var current_variant = $('#productSelect-option-0').val();
// var current_images = all_images.filter('[data-variant="'+current_variant+'"]');
all_images.each(function() {
var image_variant = $(this).attr('data-variant')
if (image_variant === current_variant) {
$('#product_carousel').append($(this));
$(this).show();
};
});
$("#product_carousel").owlCarousel({
items: 4,
itemsTablet: [768,1],
navigation: true,
navigationText: [
"<span class='icon-wrap'></span>",
"<span class='icon-wrap'></span>"
],
});
thumb_to_main();
group_images = function(variant){
$("#product_carousel").data('owlCarousel').destroy();
var current_variant = variant
all_images.each(function() {
var image_variant = $(this).attr('data-variant')
if (image_variant === current_variant) {
$('#product_carousel').append($(this));
$(this).show();
};
});
$("#product_carousel").owlCarousel({
items: 4,
itemsTablet: [768,1],
navigation: true,
navigationText: [
"<span class='icon-wrap'></span>",
"<span class='icon-wrap'></span>"
],
});
thumb_to_main();
}
$('.swatch-element.color').click(
function(){
the_variant = $(this).find('input').val()
// $('#product_carousel').trigger('destroy.owl.carousel').removeClass('owl-carousel owl-loaded');
// $('#product_carousel').find('.owl-stage-outer').children().unwrap();
// $('#product_carousel').find('.owl-controls, .owl-wrapper-outer').remove();
// owl.reinit();
images_wrapper.empty();
group_images(the_variant);
}
);
function thumb_to_main(){
var clicker = $('#product_carousel .jsThumb a')
clicker.click(function(event) {
event.preventDefault();
var need_image = $(this).attr('data-grande');
$('#ProductPhotoImg').attr('src', need_image);
});
}
});
</script>
</main>
<div class="cross-sell-wrapper">
<main class="wrapper">
<h3 class="cross-sell-title">You might also like...</h3>
<div class="grid cross-sell-content">
<div class="grid__item cross-sell large--one-third medium--one-third">
<a href="/products/the-everyday-shirt">
<img src="https://cdn.shopify.com/s/files/1/0932/9384/files/Cross_Sell_Image_Core.jpg?17896596604292023972" alt="Everyday Shirt - Heather Ash Grey">
</a>
</div>
<div class="grid__item cross-sell large--one-third medium--one-third">
<a href="/products/the-essential-jean">
<img src="https://cdn.shopify.com/s/files/1/0932/9384/files/Cross_Sell_Images16.jpg?16119080855110904862" alt="Essential Jeans - Indigo Wash">
</a>
</div>
<div class="grid__item cross-sell large--one-third medium--one-third">
<a href="/products/flannel-everyday-shirts">
<img src="https://cdn.shopify.com/s/files/1/0932/9384/files/Cross_Sell_Image_Flannel.jpg?17896596604292023972" alt="Flannel Everyday Shirt - Portland Plaid">
</a>
</div>
</div>
</main>
</div>
<div class="grid cta-wrapper">
<div class="grid__item">
<img src="https://cdn.shopify.com/s/files/1/0932/9384/files/The_Everyday_Shirt_Difference_LS.jpg?14572085892908774763" class="hero-image small--hide" alt="The Ash & Erie Difference - We looked at hundreds of details including collar size, armhole, cuff width, trail drop, inseam, rise, and much more when designing the perfect fit for our clothes">
<img src="https://cdn.shopify.com/s/files/1/0932/9384/files/The_Everyday_Shirt_Difference_Mobile_LS.jpg?1684500670335240691" class="hero-image mobile small--show medium--hide large--hide" alt="The Ash & Erie Difference - We looked at hundreds of details including collar size, armhole, cuff width, trail drop, inseam, rise, and much more when designing the perfect fit for our clothes">
</div>
</div>
<!-- Testimonials -->
<div id="testimonials2" class="testimonial-wrapper">
<main class="wrapper testimonial-info">
<div class="grid">
<div class="grid__item large--one-third testimonial abtest">
<div class="review-innerbox title">
<div class="rating">
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
</div>
<p>based on 621 reviews</p>
<hr>
<h2>Our Guys Love Their Fit</h2>
</div>
</div>
<div class="grid__item large--one-third testimonial abtest">
<div class="review-innerbox">
<div class="rating">
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
</div>
<p>"I love the fit! Nice quality and thickness to the fabric material. Shirts have not suffered any shrinkage as other brands the I have tried. Would order again!"</p>
<p class="name">Michael B. - 5'6"</p>
</div>
</div>
<div class="grid__item large--one-third testimonial abtest">
<div class="review-innerbox">
<div class="rating">
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
</div>
<p>"My boyfriend loves his shirt. It's the only shirt he can wear outside his pants. He looks so good. Plus the quality is fantastic!"</p>
<p class="name">Julie A.</p>
</div>
</div>
<div class="grid__item large--one-third testimonial abtest">
<div class="review-innerbox">
<div class="rating">
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
</div>
<p>"I am delighted with my seven shirts that I'm taking with me tomorrow on vacation. Look forward to ordering more shirts. Thanks for the two day delivery!"</p>
<p class="name">Neil R. - 5'2"</p>
</div>
</div>
<div class="grid__item large--one-third testimonial abtest">
<div class="review-innerbox">
<div class="rating">
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
</div>
<p>"As a short & fat guy, it's great to have a shirt that feels like it was cut for me. Also, when my first order turned out to be too small, you sent me next size up, and it was the right size."</p>
<p class="name">Jeff H. - 5'8"</p>
</div>
</div>
<div class="grid__item large--one-third testimonial abtest">
<div class="review-innerbox">
<div class="rating">
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
</div>
<p>"I have always had a difficult time finding shirts in the right proportions. It is such a luxury to take your shirt out of the box, put it on and have it fit perfectly!"</p>
<p class="name">Marcus K. - 5'4"</p>
</div>
</div>
</div>
</main>
</div>
<!-- Fit Guide Modal -->
<div id="openModal" class="modalDialog">
<div> <a href="#close" title="Close" class="close">X</a>
<h3>How to find the right Everyday Shirt size</h3>
<p>We’ve found that your chest size is the most important measurement when finding your Ash & Erie Everyday Shirt size. The measurements below reflect the appropriate shirt size based on your body measurements; they are not the measurements of the clothes themselves.</p>
<p>To measure your chest, wrap the tape measure under your armpits around the fullest part of your chest. The tape measure should be snug.</p>
<p>Our XS through Large shirts feature a modern fit with a 3" taper. Our XL and XXL shirts feature a classic fit with little taper.</p>
<div class="table-container size-chart-table">
<table class="responsive">
<tbody>
<tr class="table-fit">
<td class="key one">Fit Styles</td>
<td class="fit modern-fit" colspan="4">Modern Fit</td>
<td class="fit classic-fit" colspan="2">Classic Fit</td>
</tr>
<tr class="table-sizes table-title">
<td class="key one">Size</td>
<td class="size one">XS</td>
<td class="size one">S</td>
<td class="size one">M</td>
<td class="size one">L</td>
<td class="size one">XL</td>
<td class="size one">XXL</td>
</tr>
<tr>
<td class="key chest">Fits Chest Size (in.)</td>
<td class="size chest">31 - 33</td>
<td class="size chest">34 - 36</td>
<td class="size chest">37 - 39</td>
<td class="size chest">40 - 42</td>
<td class="size chest">43 - 45</td>
<td class="size chest">47 - 49</td>
</tr>
<tr>
<td class="key">Fits Sleeve Length (in.)</td>
<td class="size">30 - 31.5</td>
<td class="size">30.5 - 32</td>
<td class="size">31 - 32.5</td>
<td class="size">31.5 - 33</td>
<td class="size">32 - 33.5</td>
<td class="size">32.5 - 34</td>
</tr>
<tr>
<td class="key">Body Length (in.)</td>
<td class="size">26.5</td>
<td class="size">27</td>
<td class="size">27.5</td>
<td class="size">28</td>
<td class="size">28.5</td>
<td class="size">29.5</td>
</tr>
</tbody>
</table>
</div>
<a href="#close" title="Close" class="btn btn--secondary">Close this window</a>
</div>
</div>
<!-- Ask Us Modal -->
<div id="openModal2" class="modalDialog">
<div> <a href="#close" title="Close" class="close">X</a>
<div class="grid">
<div class="grid__item large--one-third faq">
<h3 class="faq-title">Have a question?</h3>
<p class="faq-text">Send us an email at <a href="mailto:support@ashanderie.com">support@ashanderie.com</a> or send us a chat via the bottom right corner of your screen. We will get back to you as soon as we can!</p>
</div>
<div class="grid__item large--one-third faq">
<h3 class="faq-title">Exchanges or Returns</h3>
<p class="faq-text">We offer free exchanges and returns on all US orders within 30 days, unless otherwise specified. <a href="mailto:support@ashanderie.com">Send us an email</a> with your order number to get the process started.</p>
</div>
<div class="grid__item large--one-third faq">
<h3 class="faq-title">Shipping Policy</h3>
<p class="faq-text">Enjoy FREE shipping on all US orders. All in-stock orders are shipped in 2-8 business days. Expedited shipping options are also available at checkout.</p>
</div>
</div>
<a href="#close" title="Close" class="btn btn--secondary">Close this window</a>
</div>
</div>
<!-- Bundle Modal -->
<div id="openModal3" class="modalDialog">
<div class="bundle-modal"> <a href="#close" title="Close" class="close">X</a>
<div class="grid">
<div class="grid__item large--one-half bundle-content">
<img src="https://cdn.shopify.com/s/files/1/0932/9384/files/Bundle_Image.jpg?3956264566846790320" alt="">
</div>
<div class="grid__item large--one-half bundle-content">
<h2 class="bundle-title">Save 30 bucks when you bundle.</h2>
<p class="bundle-text">Add any 3 shirts (any 3 shirts!) to your cart and use code <span class="bundle-code">NICEBUNDLE</span> at checkout to save $30 on the 3rd shirt!</p>
<a href="#close" title="Close" class="btn btn--secondary">Shop now</a>
</div>
</div>
</div>
</div>
</div>
If anyone has any ideas, would love to hear them! Appreciate all of your help and support!
Thanks,
Eric