Book a callGitHub10

Near you

Delivering to Canal Street

  • A café with a white round table and chairs

    Hollinby Bakehouse

    Rated 4.8 out of 5, (1.2k)

    Bakery · Breakfast · $$

    15–25 minFree delivery

    20% off pastries before 11 am

  • A bowl of mixed vegetable salad

    Saffrine Greens

    Rated 4.6 out of 5, (860)

    Salads · Grain bowls · $$

    20–30 min$1.99 delivery

    Buy 1, get 1 on bowls

  • A bowl of ramen with a soft egg

    Hoshiyagi Ramen Bar

    Rated 4.9 out of 5, (2.4k)

    Japanese · Ramen · $$$

    30–40 min$2.49 delivery

    New on the app

It is live: hover, focus and its own controls respond. Actions that would change data (approve, send, delete) are for your app to wire. The width is a real 390 px, 768 px or 1280 px box, shrunk to fit your screen.

Source
<!-- Icons: Lucide (lucide.dev), ISC licence -->
<style>
.odl-restaurant-card { box-sizing: border-box; inline-size: 100%; max-inline-size: 64rem; margin-inline: auto; container-type: inline-size; color: var(--ds-color-text-primary); font: var(--ds-text-body-md); text-wrap: pretty; }
.odl-restaurant-card *, .odl-restaurant-card *::before, .odl-restaurant-card *::after { box-sizing: border-box; }
.odl-restaurant-card .odl-wrap { display: grid; gap: var(--ds-space-stack-lg); padding: var(--ds-space-inset-lg); }
@container (min-width: 40rem) { .odl-restaurant-card .odl-wrap { padding: var(--ds-space-inset-xl); } }
.odl-restaurant-card .odl-top { display: grid; gap: var(--ds-space-stack-xs); }
.odl-restaurant-card h3 { margin: 0; font: var(--ds-text-title-lg); }
.odl-restaurant-card .odl-top p { margin: 0; color: var(--ds-color-text-secondary); font: var(--ds-text-label-md); }
.odl-restaurant-card ul { display: grid; gap: var(--ds-space-stack-xl) var(--ds-space-inset-xl); margin: 0; padding: 0; list-style: none; }
@container (min-width: 36rem) { .odl-restaurant-card ul { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@container (min-width: 54rem) { .odl-restaurant-card ul { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.odl-restaurant-card li { position: relative; min-inline-size: 0; inline-size: 100%; container-type: inline-size; display: grid; align-content: start; gap: var(--ds-space-stack-md); }
.odl-restaurant-card .odl-cover { position: relative; min-inline-size: 0; aspect-ratio: 16 / 10; border-radius: var(--ds-radius-container); overflow: hidden; background: var(--ds-color-surface-sunken); }
.odl-restaurant-card .odl-cover img { display: block; inline-size: 100%; max-inline-size: 100%; block-size: 100%; object-fit: cover; transition: transform var(--ds-motion-duration-medium) var(--ds-motion-easing-standard); }
.odl-restaurant-card li:hover .odl-cover img { transform: scale(1.03); }
.odl-restaurant-card .odl-fav { --odl-hang: calc((var(--ds-size-target-touch) - var(--ds-size-control-md)) / 2); position: absolute; z-index: 1; inset-block-start: calc(var(--ds-space-inset-sm) - var(--odl-hang)); inset-inline-end: calc(var(--ds-space-inset-sm) - var(--odl-hang));
  display: grid; place-items: center; inline-size: max(var(--ds-size-target-touch), var(--ds-size-control-md)); block-size: max(var(--ds-size-target-touch), var(--ds-size-control-md)); padding: 0; border: 0; border-radius: var(--ds-radius-full); background: transparent; color: var(--ds-color-text-primary); cursor: pointer; }
.odl-restaurant-card .odl-fav span { display: grid; place-items: center; inline-size: var(--ds-size-control-md); block-size: var(--ds-size-control-md); border-radius: var(--ds-radius-full); background: var(--ds-color-surface-raised); box-shadow: var(--ds-elevation-raised);
  transition: transform var(--ds-motion-duration-short) var(--ds-motion-easing-standard); }
.odl-restaurant-card .odl-fav:active span { transform: scale(var(--ds-motion-scale-press)); }
.odl-restaurant-card .odl-fav svg { inline-size: var(--ds-size-icon-sm); block-size: var(--ds-size-icon-sm); stroke-width: var(--ds-icon-stroke-md); }
.odl-restaurant-card .odl-fav[aria-pressed="true"] { color: var(--ds-color-icon-accent); }
.odl-restaurant-card .odl-fav[aria-pressed="true"] path { fill: currentColor; }
.odl-restaurant-card .odl-info { display: grid; gap: var(--ds-space-stack-xs); }
.odl-restaurant-card .odl-row { display: flex; align-items: center; justify-content: space-between; gap: var(--ds-space-inline-md); }
.odl-restaurant-card h4 { margin: 0; min-inline-size: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font: var(--ds-text-title-sm); }
.odl-restaurant-card h4 a { color: inherit; text-decoration: none; }
.odl-restaurant-card h4 a::after { content: ""; position: absolute; inset: 0; }
.odl-restaurant-card h4 a:focus-visible { outline: none; }
.odl-restaurant-card li:has(h4 a:focus-visible) .odl-cover { outline: var(--ds-focus-ring-width) solid var(--ds-color-border-focus); outline-offset: var(--ds-focus-ring-offset); }
.odl-restaurant-card .odl-rating { flex: none; display: inline-flex; align-items: center; gap: var(--ds-space-inline-xs); font: var(--ds-text-label-md); font-variant-numeric: tabular-nums; }
.odl-restaurant-card .odl-rating svg { inline-size: var(--ds-size-icon-sm); block-size: var(--ds-size-icon-sm); stroke-width: var(--ds-icon-stroke-md); }
.odl-restaurant-card .odl-count { color: var(--ds-color-text-tertiary); }
@container (max-width: 16rem) { .odl-restaurant-card .odl-count { display: none; } }
.odl-restaurant-card .odl-cuisine { margin: 0; color: var(--ds-color-text-secondary); font: var(--ds-text-body-md); }
.odl-restaurant-card .odl-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ds-space-stack-xs) var(--ds-space-inset-lg); margin: 0; color: var(--ds-color-text-secondary); font: var(--ds-text-label-md); font-variant-numeric: tabular-nums; }
.odl-restaurant-card .odl-meta span { display: inline-flex; align-items: center; gap: var(--ds-space-inline-xs); white-space: nowrap; }
.odl-restaurant-card .odl-meta svg, .odl-restaurant-card .odl-promo svg { flex: none; inline-size: var(--ds-size-icon-sm); block-size: var(--ds-size-icon-sm); stroke-width: var(--ds-icon-stroke-md); color: var(--ds-color-icon-subtle); }
.odl-restaurant-card .odl-promo { display: flex; align-items: center; gap: var(--ds-space-inline-xs); justify-self: start; max-inline-size: 100%; margin: var(--ds-space-stack-xs) 0 0; padding: var(--ds-space-inset-xs) var(--ds-space-inset-sm); border-radius: var(--ds-radius-control-sm);
  background: var(--ds-color-bg-neutral-subtle); color: var(--ds-color-text-primary); font: var(--ds-text-label-md); }
.odl-restaurant-card .odl-promo { align-items: flex-start; }
.odl-restaurant-card .odl-promo svg { margin-block-start: var(--ds-space-2); }
.odl-restaurant-card button:focus-visible { outline: none; }
.odl-restaurant-card button:focus-visible span { outline: var(--ds-focus-ring-width) solid var(--ds-color-border-focus); outline-offset: var(--ds-focus-ring-offset); }
.odl-restaurant-card .odl-sr { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
@media (prefers-reduced-motion: reduce) { .odl-restaurant-card, .odl-restaurant-card *, .odl-restaurant-card *::before { transition: none !important; animation: none !important; } }
</style>
<section class="odl-restaurant-card" aria-labelledby="odl-rc-title">
  <div class="odl-wrap">
    <div class="odl-top"><h3 id="odl-rc-title">Near you</h3><p>Delivering to Canal Street</p></div>
    <ul>
      <li>
        <div class="odl-cover">
          <img src="https://images.unsplash.com/photo-1583354608715-177553a4035e?w=720&h=450&fit=crop&auto=format&q=70" alt="A café with a white round table and chairs" width="360" height="225" loading="lazy" decoding="async">
          <button type="button" class="odl-fav" aria-label="Save Hollinby Bakehouse" aria-pressed="true"><span><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/></svg></span></button>
        </div>
        <div class="odl-info">
          <div class="odl-row"><h4><a href="#">Hollinby Bakehouse</a></h4><span class="odl-rating"><svg viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.010a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z"/></svg><span class="odl-sr">Rated </span>4.8<span class="odl-sr"> out of 5,</span> <span class="odl-count">(1.2k)</span></span></div>
          <p class="odl-cuisine">Bakery · Breakfast · $$</p>
          <p class="odl-meta"><span><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>15–25 min</span><span><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="18.5" cy="17.5" r="3.5"/><circle cx="5.5" cy="17.5" r="3.5"/><circle cx="15" cy="5" r="1"/><path d="M12 17.5V14l-3-3 4-3 2 3h2"/></svg>Free delivery</span></p>
          <p class="odl-promo"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z"/><circle cx="7.5" cy="7.5" r=".5" fill="currentColor"/></svg>20% off pastries before 11 am</p>
        </div>
      </li>
      <li>
        <div class="odl-cover">
          <img src="https://images.unsplash.com/photo-1512621776951-a57141f2eefd?w=720&h=450&fit=crop&auto=format&q=70" alt="A bowl of mixed vegetable salad" width="360" height="225" loading="lazy" decoding="async">
          <button type="button" class="odl-fav" aria-label="Save Saffrine Greens" aria-pressed="false"><span><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/></svg></span></button>
        </div>
        <div class="odl-info">
          <div class="odl-row"><h4><a href="#">Saffrine Greens</a></h4><span class="odl-rating"><svg viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.010a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z"/></svg><span class="odl-sr">Rated </span>4.6<span class="odl-sr"> out of 5,</span> <span class="odl-count">(860)</span></span></div>
          <p class="odl-cuisine">Salads · Grain bowls · $$</p>
          <p class="odl-meta"><span><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>20–30 min</span><span><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="18.5" cy="17.5" r="3.5"/><circle cx="5.5" cy="17.5" r="3.5"/><circle cx="15" cy="5" r="1"/><path d="M12 17.5V14l-3-3 4-3 2 3h2"/></svg>$1.99 delivery</span></p>
          <p class="odl-promo"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z"/><circle cx="7.5" cy="7.5" r=".5" fill="currentColor"/></svg>Buy 1, get 1 on bowls</p>
        </div>
      </li>
      <li>
        <div class="odl-cover">
          <img src="https://images.unsplash.com/photo-1569718212165-3a8278d5f624?w=720&h=450&fit=crop&auto=format&q=70" alt="A bowl of ramen with a soft egg" width="360" height="225" loading="lazy" decoding="async">
          <button type="button" class="odl-fav" aria-label="Save Hoshiyagi Ramen Bar" aria-pressed="false"><span><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/></svg></span></button>
        </div>
        <div class="odl-info">
          <div class="odl-row"><h4><a href="#">Hoshiyagi Ramen Bar</a></h4><span class="odl-rating"><svg viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.010a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z"/></svg><span class="odl-sr">Rated </span>4.9<span class="odl-sr"> out of 5,</span> <span class="odl-count">(2.4k)</span></span></div>
          <p class="odl-cuisine">Japanese · Ramen · $$$</p>
          <p class="odl-meta"><span><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>30–40 min</span><span><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="18.5" cy="17.5" r="3.5"/><circle cx="5.5" cy="17.5" r="3.5"/><circle cx="15" cy="5" r="1"/><path d="M12 17.5V14l-3-3 4-3 2 3h2"/></svg>$2.49 delivery</span></p>
          <p class="odl-promo"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"/><path d="M20 3v4"/><path d="M22 5h-4"/><path d="M4 17v2"/><path d="M5 18H3"/></svg>New on the app</p>
        </div>
      </li>
    </ul>
  </div>
</section>
<script>
document.querySelectorAll(".odl-restaurant-card").forEach((root) => {
  if (root.dataset.odlReady) return; // wire once, even if the file is pasted twice
  root.dataset.odlReady = "1";
  root.querySelectorAll(".odl-fav").forEach((b) => b.addEventListener("click", () => {
    const on = b.getAttribute("aria-pressed") !== "true"; b.setAttribute("aria-pressed", String(on));
  }));
  root.querySelectorAll("h4 a").forEach((a) => a.addEventListener("click", (e) => { if (a.getAttribute("href") === "#") e.preventDefault(); }));
});
</script>

More like this

ConsumerFriendly · Travel

Stay card

A holiday rental or hotel listing: a swipeable photo carousel with dots, a favourite heart, the place, host and dates, the rating, and the price per night with the total.

B2BFriendly · SaaS

Plan picker

Three plans as cards you select, with a monthly or yearly switch that changes the prices and one plan marked as the common choice.

Your kit

Nothing here yet. Add parts with Add to kit, and a look if you want the whole system.

    Parts
    0
    Files to fetch
    0 KB
    Licence
    MIT
    Total
    Free, now and later

    How do you want it?

    Your prompt

    No sign-up. Nothing leaves your browser until you paste it.

    Free