This custom code is completely free to use, but please note it does not include 1-on-1 technical support. If you need a bespoke, done-for-you solution to customize your Shopify store, my team is here to help! Head to my channel homepage and use the link in the trailer to reach out.
{% comment %}
<!-- Designed by ONHOW Studio YouTube Channel - Anas El Medlaoui -->
{% endcomment %}
{% if product.metafields.custom.complementary_products.value != blank %}
<style>
.onhow-studio-comp-container {
margin: 20px 0;
border-top: 1px solid rgba(var(--color-foreground, 0, 0, 0), 0.1);
border-bottom: 1px solid rgba(var(--color-foreground, 0, 0, 0), 0.1);
font-family: inherit;
}
.onhow-studio-comp-details {
width: 100%;
}
.onhow-studio-comp-summary {
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
padding: 13px 14px;
font-size: 1.1em;
font-weight: 600;
list-style: none;
color: inherit;
background-color: color-mix(in srgb, currentColor 5%, transparent);
border-radius: 6px;
border-left: 3px solid color-mix(in srgb, currentColor 20%, transparent);
}
.onhow-studio-comp-summary::-webkit-details-marker {
display: none;
}
.onhow-studio-comp-icon {
width: 22px;
height: 22px;
flex-shrink: 0;
transition: transform 0.5s ease;
}
.onhow-studio-comp-details[open] .onhow-studio-comp-icon {
transform: rotate(180deg);
}
@keyframes onhow-comp-open {
from {
opacity: 0;
transform: translateY(-8px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes onhow-comp-close {
from {
opacity: 1;
transform: translateY(0);
}
to {
opacity: 0;
transform: translateY(-8px);
}
}
.onhow-studio-comp-details[open] .onhow-studio-comp-grid {
animation: onhow-comp-open 0.45s ease forwards;
}
.onhow-studio-comp-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
gap: 15px;
padding-top: 5px;
padding-bottom: 20px;
}
.onhow-studio-comp-card {
display: flex;
flex-direction: column;
gap: 8px;
}
.onhow-studio-comp-image-link {
display: block;
position: relative;
width: 100%;
padding-bottom: 100%;
background-color: rgba(var(--color-foreground, 0, 0, 0), 0.03);
border-radius: min(var(--border-radius, 4px), 4px);
overflow: hidden;
text-decoration: none;
}
.onhow-studio-comp-image,
.onhow-studio-comp-placeholder {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
.onhow-studio-comp-card:hover .onhow-studio-comp-image {
transform: scale(1.03);
}
.onhow-studio-comp-placeholder {
fill: rgba(var(--color-foreground, 0, 0, 0), 0.2);
}
.onhow-studio-comp-title {
font-size: 0.9em;
line-height: 1.3;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
color: inherit;
text-decoration: none;
}
.onhow-studio-comp-price {
font-size: 0.9em;
font-weight: 700;
color: inherit;
}
.onhow-studio-comp-price-compare {
font-weight: 400;
font-size: 0.85em;
color: rgba(var(--color-foreground, 0, 0, 0), 0.6);
margin-left: 0.3rem;
}
.onhow-studio-comp-form {
display: flex;
flex-direction: column;
gap: 6px;
margin-top: auto;
}
.onhow-studio-comp-variant-select {
width: 100%;
padding: 0.4rem;
border: 1px solid rgba(var(--color-foreground, 0, 0, 0), 0.1);
border-radius: min(var(--border-radius, 4px), 4px);
background: transparent;
font-size: 0.8rem;
font-family: inherit;
color: inherit;
appearance: auto;
cursor: pointer;
}
.onhow-studio-comp-button {
width: 100%;
padding: 0.5rem;
background-color: rgb(var(--color-button, 0, 0, 0));
color: rgb(var(--color-button-text, 255, 255, 255));
border: none;
border-radius: min(var(--border-radius, 4px), 4px);
cursor: pointer;
font-weight: 600;
font-size: 0.8rem;
font-family: inherit;
text-align: center;
letter-spacing: inherit;
text-transform: inherit;
transition: opacity 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
}
.onhow-studio-comp-button:hover:not(:disabled) {
opacity: 0.85;
}
.onhow-studio-comp-button:disabled {
background-color: rgba(var(--color-foreground, 0, 0, 0), 0.1);
color: rgba(var(--color-foreground, 0, 0, 0), 0.4);
cursor: not-allowed;
}
@media screen and (max-width: 768px) {
.onhow-studio-comp-grid {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
padding-bottom: 1rem;
-webkit-overflow-scrolling: touch;
margin-right: -1.5rem;
padding-right: 1.5rem;
}
.onhow-studio-comp-grid::-webkit-scrollbar {
height: 4px;
}
.onhow-studio-comp-grid::-webkit-scrollbar-thumb {
background-color: rgba(var(--color-foreground, 0, 0, 0), 0.15);
border-radius: 4px;
}
.onhow-studio-comp-card {
flex: 0 0 130px;
scroll-snap-align: start;
}
}
</style>
<div class="onhow-studio-comp-container">
<details class="onhow-studio-comp-details" open>
<summary class="onhow-studio-comp-summary">
Pairs well with
<svg class="onhow-studio-comp-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</summary>
<div class="onhow-studio-comp-grid">
{% for item in product.metafields.custom.complementary_products.value %}
{% if item.available %}
<div class="onhow-studio-comp-card">
<a href="{{ item.url }}" class="onhow-studio-comp-image-link">
{% if item.featured_image %}
<img
class="onhow-studio-comp-image"
src="{{ item.featured_image | image_url: width: 400 }}"
alt="{{ item.title | escape }}"
loading="lazy"
width="400"
height="400"
>
{% else %}
{{ 'product-1' | placeholder_svg_tag: 'onhow-studio-comp-placeholder' }}
{% endif %}
</a>
<a href="{{ item.url }}" class="onhow-studio-comp-title">{{ item.title }}</a>
<div class="onhow-studio-comp-price">
{% if item.compare_at_price > item.price %}
<span>{{ item.price | money }}</span>
<s class="onhow-studio-comp-price-compare">{{ item.compare_at_price | money }}</s>
{% else %}
<span>{{ item.price | money }}</span>
{% endif %}
</div>
<form class="onhow-studio-comp-form">
{% if item.has_only_default_variant %}
<input type="hidden" name="id" value="{{ item.selected_or_first_available_variant.id }}">
{% else %}
<select name="id" class="onhow-studio-comp-variant-select">
{% for variant in item.variants %}
<option
value="{{ variant.id }}"
{% unless variant.available %}disabled{% endunless %}
{% if variant == item.selected_or_first_available_variant %}selected{% endif %}
>
{{ variant.title }} — {{ variant.price | money }}
</option>
{% endfor %}
</select>
{% endif %}
<button
type="submit"
class="onhow-studio-comp-button"
{% unless item.selected_or_first_available_variant.available %}disabled{% endunless %}
>
{% if item.selected_or_first_available_variant.available %}
Add to cart
{% else %}
Sold out
{% endif %}
</button>
</form>
</div>
{% endif %}
{% endfor %}
</div>
</details>
</div>
<script>
(function () {
document.querySelectorAll('.onhow-studio-comp-summary').forEach(function (summary) {
summary.addEventListener('click', function (e) {
var details = summary.closest('.onhow-studio-comp-details');
if (!details || !details.open) return;
e.preventDefault();
var grid = details.querySelector('.onhow-studio-comp-grid');
if (!grid) { details.removeAttribute('open'); return; }
grid.style.animation = 'onhow-comp-close 0.4s ease forwards';
grid.addEventListener('animationend', function () {
grid.style.animation = '';
details.removeAttribute('open');
}, { once: true });
});
});
document.addEventListener('change', function (e) {
if (!e.target.classList.contains('onhow-studio-comp-variant-select')) return;
var form = e.target.closest('.onhow-studio-comp-form');
var btn = form && form.querySelector('.onhow-studio-comp-button');
if (!btn) return;
var selected = e.target.options[e.target.selectedIndex];
btn.disabled = selected.disabled;
btn.textContent = selected.disabled ? 'Sold out' : 'Add to cart';
});
document.addEventListener('submit', function (e) {
if (!e.target.classList.contains('onhow-studio-comp-form')) return;
e.preventDefault();
var form = e.target;
var btn = form.querySelector('.onhow-studio-comp-button');
var originalText = btn.innerText;
var variantId = Number(new FormData(form).get('id'));
var sectionId = (document.querySelector('cart-items-component[data-drawer]') || {}).dataset?.sectionId;
btn.disabled = true;
btn.innerText = 'Adding...';
var payload = { items: [{ id: variantId, quantity: 1 }] };
if (sectionId) payload.sections = sectionId;
fetch(
(window.Shopify && window.Shopify.routes && window.Shopify.routes.root
? window.Shopify.routes.root
: '/') + 'cart/add.js',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
},
body: JSON.stringify(payload),
}
)
.then(function (r) {
if (!r.ok) throw new Error('add failed');
return r.json();
})
.then(function (data) {
btn.innerText = 'Added ✓';
btn.disabled = true;
document.dispatchEvent(
new CustomEvent('cart:update', {
bubbles: true,
detail: {
resource: data,
sourceId: 'onhow-studio-comp',
data: {
sections: data.sections || {},
},
},
})
);
var drawer = document.querySelector('cart-drawer-component');
if (drawer && typeof drawer.open === 'function') drawer.open();
})
.catch(function () {
btn.innerText = 'Error';
setTimeout(function () {
btn.innerText = originalText;
btn.disabled = false;
}, 2000);
});
});
})();
</script>
{% endif %}
{% comment %}
<!-- Designed by ONHOW Studio YouTube Channel - Anas El Medlaoui -->
{% endcomment %}

