2.0 Beta

Smootify 2.0 is in public beta. Your 1.x store keeps working. Move when you want.

What changed

Product cards

A product card is a smootify-product that shows one product in a list. Covers what a card needs, what it can show (price ranges, option values, badges), adding to cart from a card, cards in a slider and placeholder cards.

v2.0 beta
Open .md
On this page
  1. What a card needs
  2. What a card can show
  3. Link and image
  4. Prices
  5. Option values
  6. Badges and labels
  7. Add to cart from a card
  8. Cards in a slider
  9. Placeholder cards
  10. Before you publish

A product card shows one product in a list: the entries of the products collection, a search & discovery grid, a slider or a list of best sellers. In Smootify every card is the same element as the product page, smootify-product, holding a smaller design. This page covers what a card needs, what it can show, and how to add to the cart from it.

Note

Before you start, your products must be loaded as the products content collection: see Content from Shopify.

What a card needs

  • A smootify-product element with the product’s id. In a list of entries, render each card as an element with the class sm-dyn-item, the boundary of the card, with the smootify-product inside it and its data-id set to the entry’s shopifyId. In the lists Smootify fills itself (search & discovery, the search page, best sellers and the other product lists), you write one card and Smootify gives each copy its product.
  • Everything else is optional. Every attribute of the product page works inside a card: title, prices, conditions, metafields, even a gallery or an add-to-cart form. A card usually needs fewer of them.
---
const p = entry.data;
---
<div class="sm-dyn-item">
  <smootify-product data-id={p.shopifyId}>
    <a product="link" href={`/products/${entry.id}/`}><img variant="image" src={p.image} alt={p.imageAlt} width={p.imageWidth} height={p.imageHeight}></a>
    <a product="url" href={`/products/${entry.id}/`}>{p.name}</a>
    <smootify-price><span data-prop="price">{p.priceFormatted}</span></smootify-price>
  </smootify-product>
</div>

Render the links, the image, the name and the price from the entry. The card works before Smootify loads, and search engines read it; Smootify then writes the live values from Shopify.

A few things work differently on a card:

  • it ignores ?variant= in the address, which is only for the page’s own product;
  • it starts on the first variant that can be bought, or on the first variant when none can;
  • when Shopify does not return the product (it is unpublished, or not sold in the visitor’s market), Smootify sets hidden on the card, its sm-dyn-item.

What a card can show

Four attributes fill the link and the pictures of a card:

AttributePut it onWhat it does
product="url"an <a>gets the product page’s link, and the product title when the link holds only text
product="link"an <a> that wraps the image or the whole cardgets the link only
variant="image"an <img>shows the image of the card’s variant; render the entry’s image in it, and it shows until the product loads
product="specific-image"an <img>shows one image by position: index="0" is the first image, index="1" the second; without index, the second image, such as a picture shown on hover

Images Smootify writes accept size attributes such as max-width, so the card does not download a full-size photo: see image size.

Prices

smootify-price shows the price of the card’s variant, as on the product page. variant="unit-price" adds its price per unit, such as €1.50/ 100 g (Price per unit). For the range of the product’s variants, use these attributes on text. Here on a shirt in four sizes, with S on sale and sold out:

product="min-price"product="max-price"
Shows
The lowest and the highest variant price.
Here
$29 (S) and $39 (XL).
product="min-available-price"
Shows
The price of the cheapest variant that can be bought.
Here
$32: S is sold out, so M.
product="min-compare-at-price"product="max-compare-at-price"
Shows
The lowest and the highest crossed-out price among the variants on sale. Hidden when none is on sale.
Here
$39 (S) and $45 (M).
condition="variable-price"condition="fixed-price"
Shows
variable-price: only when the variants have different prices. fixed-price: only when they all cost the same.
Here
The prices differ, so "From" shows.

Every value is in product values. With the minimum prices, condition="variable-price" gives “From $29 $39”:

<div><span condition="variable-price">From </span><span product="min-price">$0.00</span> <span product="min-compare-at-price">$0.00</span></div>

Option values

product="option-values" shows the values of one option, such as the colour dots under a card. Smootify makes one copy of the element per value.

<div product="option-values" data-option-name="Color,Colour"><div option="bg-color"></div></div>
  • Pick the option with data-option-name="Color,Colour" (the first of those names the product has, written as in Shopify) or data-option="2" (the second option; the default is the first).
  • Inside the element, option="bg-color" or option="color" paints the value’s colour as a background or as the text colour, option="image" shows its image and option="title" its name. A copy without any of these shows the value’s name as text.
  • The colours and images come from Shopify: see Swatch colours and images.
  • The element is removed when the product does not have that option.
  • A link with product="link" inside a copy opens the product with that value already chosen (the first available variant with it).
  • More in option values.

Option values only show. To let the visitor pick a value on the card, use a picker such as variant-swatches inside the card: it changes the card’s variant, its image and its price.

Badges and labels

  • States. condition="on-sale" (and its opposite not-on-sale), in-stock, out-of-stock, low-stock and the other product conditions work on cards. condition="is-new" shows a “New” badge while the product was published less than 30 days ago; data-new-days="14" on smootify-product changes the days.
  • Discount. variant="discount-percentage" shows the discount of the card’s variant. Put it inside an element with condition="on-sale", since it shows 0% otherwise.
  • Tags. An element with tagged="bestseller" stays only when the product has that tag, and not-tagged does the opposite: see tag conditions.
  • Collections and vendor. product="collections" makes one copy per collection, with its link on a Text link; exclude="Home, Sale" leaves some out. product="first-collection" shows one. product="vendor" on a Text link links to the vendor page.

Hide a card that is already in the cart. Add hide-if-product-in-cart to smootify-product. The card (its sm-dyn-item) is hidden while a cart line holds the product. It is useful for “You may also like” lists. The value false turns it off, in any case, so a component can drive it with a boolean prop. In a slider, the card’s whole slide is hidden.

While it loads. Add skeleton="text", "image" or another loading value to the elements that should shimmer until the product loads.

Add to cart from a card

There are two ways:

WayBuilt withAddsGood to know
A direct buttona <button> with data-is="direct-add-to-cart", anywhere inside smootify-product; no formthe card’s variant, quantity 1disabled, with the class is-disabled, when the variant cannot be bought; it does not close the cart, so it works on cards inside the cart, such as cart upsells
A full forma smootify-add-to-cart with a <form> inside the card, as on the product pagethe quantity, the options and the extra fields of the formnot on cards inside the cart’s form: a <form> cannot sit inside another

The direct button is a <button> with the attribute data-is="direct-add-to-cart":

<button data-is="direct-add-to-cart"><span data-state="default">Add to cart</span><span data-state="loading">Adding…</span></button>
  • The elements with data-state="default" and data-state="loading" swap while the product is added. Both are optional.
  • With a picker on the card, the button adds the variant the visitor picked.
  • It adds one piece, or the variant’s minimum when it has purchase rules or a B2B quantity rule.

The full form is built as in step 6 of Build the product page. Use it when the card needs a quantity field, options inside the form or extra fields.

A link (<a>) cannot add to the cart. Use a <button> tag.

Cards in a slider

A slider of cards is a [slider-track] element whose children are the cards, each card its slide. The optional [slider-prev] and [slider-next] buttons and a [slider-dots] element sit next to the track. Smootify does not run them here: the site’s own slider script does. Smootify runs them only in the media sliders of the product page and in Magic Box. The track scrolls with scroll snap: its CSS gives it overflow-x: auto and scroll-snap-type. There is no product-slider element on Astro.

There are two ways to fill it:

  • With entries. Render one card for each entry of a collection on the server, so the HTML has real content.
  • With a Smootify source. Write one template card with data-id set to the source, such as related, best-seller, last-viewed or a specific collection, and Smootify clones the slide for each product: see Product lists.
---
const { products } = Astro.props; // entries of the products collection
---
<div data-carousel>
  <div slider-track>
    {products.map(({ id, data }) => (
      <div class="sm-dyn-item">
        <smootify-product data-id={data.shopifyId}>
          <a product="link" href={`/products/${id}/`}><img variant="image" src={data.image} alt={data.imageAlt} /></a>
          <a product="url" href={`/products/${id}/`}>{data.name}</a>
        </smootify-product>
      </div>
    ))}
  </div>
  <button type="button" slider-prev aria-label="Previous" disabled>&lsaquo;</button>
  <button type="button" slider-next aria-label="Next">&rsaquo;</button>
</div>

For a slider of cards, the component wires its own arrows and dots with a small <script>, and a slider of static content works the same way. How these parts are written is in Write components.

Placeholder cards

Placeholder cards, which are a smootify-product with data-id="loader", are not needed on Astro. Render the real cards on the server:

  • in search & discovery and on the search page, the card template is the first smootify-product of the block, whatever its data-id. The cards of the list stay as they are until the first results: Smootify keeps them when the results are the same products in the same order, as the first page served from the seed is, and otherwise replaces them in one step, so the page does not jump;
  • a slider filled by a product list such as best sellers is one template card with the list’s data-id: Smootify clones its slide for each product. There are no placeholder slides.

More in smootify-product[data-id="loader"].

Before you publish

Check these first

  • Every card shows the same product. data-id holds a fixed id. Set it to the entry’s shopifyId.
  • A card is missing or empty. Shopify did not return that product: it is not published to the sales channel, or not sold in the visitor’s market. Its card gets hidden.
  • The colour dots show names instead of colours. The option’s values have no swatch in Shopify and no option metaobject. See Swatch colours and images.
  • The add button does nothing. It is not a <button> tag. Use <button data-is="direct-add-to-cart">.
  • “0% off” on products that are not on sale. Put variant="discount-percentage" inside an element with condition="on-sale".

    ↑ ↓ to moveEnter to openEsc to close