Velmora Reviews Reviews Block - Let's templates
Unlock every premium block and template with All-Access from $20 / 3 months, cancel anytime. Get All-Access
All blocks
Free Reviews

Velmora Reviews

A reviews block extracted from the Velmora template, available in Tailwind CSS and Bootstrap.

0 1
Velmora Reviews preview
velmora.html
<!DOCTYPE html>
<html lang="en">
<head>
  <script>
    window.FontAwesomeConfig = { autoReplaceSvg: 'nest' };
  </script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Velmora Reviews | Tailwind CSS UI Block</title>
  <meta name="description" content="A reviews block extracted from the Velmora template, available in Tailwind CSS and Bootstrap.">
  <meta name="keywords" content="Velmora, Tailwind CSS template, HTML website template, interior design template, architecture studio, design agency, portfolio, case studies">
  <meta name="author" content="Let's templates">
  <link rel="canonical" href="">

  <meta property="og:type" content="product">
  <meta property="og:site_name" content="Let's templates">
  <meta property="og:locale" content="en_US">
  <meta property="og:url" content="">
  <meta property="og:title" content="Velmora | Tailwind CSS Agency Template">
  <meta property="og:description" content="A calm Tailwind CSS interior design studio template with an organic photo hero, scrolling room gallery, project spotlights, a process map and material swatches.">
  <meta property="og:image" content="">
  <meta property="og:image:alt" content="Velmora template preview">

  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:url" content="">
  <meta name="twitter:title" content="Velmora | Tailwind CSS Agency Template">
  <meta name="twitter:description" content="A calm Tailwind CSS interior design studio template with an organic photo hero, scrolling room gallery, project spotlights, a process map and material swatches.">
  <meta name="twitter:image" content="">
  <meta name="twitter:image:alt" content="Velmora template preview">
  <script src="https://cdn.tailwindcss.com/3.4.17"></script>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&display=swap" rel="stylesheet">
  <script>
    tailwind.config = {
      theme: {
        extend: {
          colors: {
            ink: '#121212',
            stone: '#f4f4f4',
            ember: '#e5483d'
          },
          fontFamily: {
            sans: ['Inter', 'ui-sans-serif', 'system-ui', 'sans-serif']
          }
        }
      }
    };
  </script>
  <style>
    @view-transition { navigation: auto; }
    ::view-transition-old(root) { animation: 180ms ease-out both page-fade-out; }
    ::view-transition-new(root) { animation: 220ms ease-in both page-fade-in; }
    @keyframes page-fade-out { to { opacity: 0; } }
    @keyframes page-fade-in { from { opacity: 0; } }
    @keyframes marquee { to { transform: translateX(-50%); } }
    html { scroll-behavior: smooth; }
    [hidden] { display: none !important; }
    .sketch { filter: grayscale(1) contrast(1.6) brightness(1.35); opacity: .22; mask-image: radial-gradient(ellipse at center, #000 35%, transparent 75%); }
    .blob { border-radius: 58% 42% 55% 45% / 48% 58% 42% 52%; mask-image: radial-gradient(closest-side, #000 86%, transparent 100%); }
    .blob-small { border-radius: 45% 55% 40% 60% / 55% 45% 60% 40%; mask-image: radial-gradient(closest-side, #000 82%, transparent 100%); }
    .marquee-track { animation: marquee 48s linear infinite; }
    .marquee:hover .marquee-track { animation-play-state: paused; }
    .swatch { clip-path: polygon(0 0, 62% 0, 100% 22%, 100% 100%, 0 100%); }
    .swatch-wood { background: repeating-linear-gradient(92deg, #6b4428 0 3px, #7a4f30 3px 7px, #5d3a22 7px 9px, #8a5a36 9px 14px); }
    .swatch-brick { background-color: #9c4a36; background-image: linear-gradient(#d9d3cc 2px, transparent 2px), linear-gradient(90deg, #d9d3cc 2px, transparent 2px); background-size: 34px 16px, 34px 32px; background-position: 0 0, 17px 16px; }
    .swatch-concrete { background-color: #6f716f; background-image: radial-gradient(#5a5c5b 1px, transparent 1.5px), radial-gradient(#8a8c8a 1px, transparent 1.5px); background-size: 9px 9px, 13px 13px; background-position: 0 0, 4px 6px; }
    .swatch-glass { background: linear-gradient(135deg, #2c3640 0%, #5b6b78 30%, #1f262c 46%, #6e7f8c 62%, #2a3138 100%); }
    .reveal-ready [data-reveal] { opacity: 0; transform: translateY(24px); transition: opacity .6s ease, transform .6s ease; transition-delay: var(--reveal-delay, 0ms); }
    .reveal-ready [data-reveal].is-visible { opacity: 1; transform: none; }
    @media (prefers-reduced-motion: reduce) {
      html { scroll-behavior: auto; }
      .marquee-track { animation: none; }
      ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
    }
  </style>
</head>
<body class="bg-white font-sans text-ink antialiased">
<% active_page = "index" %>
<% [{ "resources" => "Resources", "enterprise" => "Enterprise" }, { "work" => "Work", "services" => "Services", "process" => "Process" }].each do |column| %>
<% column.each do |slug, label| %>
<% active = active_page == slug %>
<% end %>
<% end %>
<% { "index" => "Home", "work" => "Work", "services" => "Services", "process" => "Process", "resources" => "Resources", "enterprise" => "Enterprise", "contact" => "Start a space" }.each do |slug, label| %>
<% active = active_page == slug %>
<% end %>
<% rooms = [
      ["1505693416388-ac5ce068fe85", "Bedroom with an upholstered headboard and soft linen"],
      ["1493663284031-b7e3aefcae8e", "Grey sofa with teal cushions under a bright window"],
      ["1586023492125-27b2c045efd7", "Yellow armchair beside a floor lamp and framed print"],
      ["1615873968403-89e068629265", "Living room with a deep green wall and leather sofa"],
      ["1556228453-efd6c1ff04f6", "Pastel lounge with blush armchairs and a woven wall hanging"],
      ["1617104678098-de229db51175", "Dark bedroom with a garden view"]
    ] %>
<% (rooms * 2).each_with_index do |(image, alt), index| %>
<% end %>
<% [
          ["1502672260266-1c1ef2d93688", "left-[18%] top-[6%]"], ["1501045661006-fcebe0257c3f", "left-[50%] top-0"],
          ["1594026112284-02bb6f3352fe", "left-[6%] top-[30%]"], ["1567225557594-88d73e55f2cb", "right-[2%] top-[30%]"],
          ["1554118811-1e0d58224f24", "left-[38%] top-[44%]"], ["1484154218962-a197022b5858", "right-[12%] top-[55%]"],
          ["1595526114035-0d45ed16cfbf", "left-[16%] top-[62%]"], ["1560448204-e02f11c3d0e2", "left-[46%] top-[80%]"]
        ].each_with_index do |(image, place), index| %>
<% end %>
<% [
        ["Spatial Planning", "Flow before finishes", "#1f6fb2", "M100 8 L190 190 L12 150 Z", "M86 70 C92 52 108 52 114 70 L124 84 C132 92 128 100 118 104 L124 122 C126 132 118 136 100 136 C82 136 74 132 76 122 L82 104 C72 100 68 92 76 84 Z"],
        ["Lighting Design", "Shadows on purpose", "#d9443a", "M40 10 L120 28 L122 70 L176 96 L140 190 L50 182 L18 120 Z", "M84 66 C96 56 110 66 112 80 C126 86 122 104 116 116 L104 136 C98 140 92 136 82 124 C76 112 78 96 80 84 Z"],
        ["Custom Furniture", "Pieces that belong", "#2fa53a", "M48 8 L96 60 L110 46 L172 58 L172 182 L118 156 L58 190 L20 104 Z", "M70 112 L86 74 C92 66 98 70 98 78 L104 92 L112 70 C116 62 126 64 126 72 L128 126 C128 132 120 134 116 128 L104 108 L90 128 C84 134 74 130 72 122 Z"],
        ["Material Direction", "Texture you can feel", "#c58a10", "M54 8 L96 70 L180 14 L160 116 L120 186 L36 156 L12 96 Z", "M66 88 L90 76 L108 88 L130 80 L156 88 C160 92 158 98 152 102 L108 136 C102 140 96 138 92 132 Z"]
      ].each_with_index do |(title, line, color, outline, mark), index| %>
<% end %>
<% [
        ["sunday-loft", "Sunday Loft", "Lisbon, 2025", "1600210492486-724fe5c67fb0", "Bright living room with a leather sofa and gallery wall", [["Type", "Residential"], ["Size", "96 m²"], ["Scope", "Interior Design"]], "bg-neutral-600/40"],
        ["ember-cafe", "Ember Corner Café", "Porto, 2026", "1554118811-1e0d58224f24", "Café with plants, rattan chairs and a chalkboard menu", [["Type", "Hospitality"], ["Size", "150 m²"], ["Scope", "Material Direction"]], "bg-black/40"]
      ].each_with_index do |(slug, title, place, image, alt, facts, glass), index| %>
<% facts.each do |label, value| %>
<% end %>
<% end %>
<% steps = [["Listen", "We watch how you live"], ["Interpret", "Habits become geometry"], ["Compose", "The space finds its rhythm"], ["Build", "Makers follow the story"], ["Live", "The room grows with you"]] %>
<% steps.each_with_index do |(title, copy), index| %>
<% end %>
<% [["left-[0%] top-[4%]"], ["left-[24%] top-[25%]"], ["left-[66%] top-[16%]"], ["left-[52%] top-[56%]"], ["left-[80%] top-[72%]"]].each_with_index do |(place), index| %>
<% title, copy = steps[index] %>
<% end %>
<% [["1594026112284-02bb6f3352fe", "left-[28%] top-[60%] w-52"], ["1567225557594-88d73e55f2cb", "left-[56%] top-[36%] w-44"], ["1556228453-efd6c1ff04f6", "left-[64%] top-[78%] w-44"]].each do |image, place| %>
<% end %>
<% [
        ["Oak", "Warm grain for built-in joinery and wall panelling.", "swatch-wood"],
        ["Brick", "Reclaimed texture for feature walls and fireplaces.", "swatch-brick"],
        ["Concrete", "Honest, cool surfaces for floors and counters.", "swatch-concrete"],
        ["Glass", "Fluted screens that share light but keep privacy.", "swatch-glass"]
      ].each_with_index do |(title, copy, swatch), index| %>
<% end %>
<!-- block:start reviews -->
  <section id="testimonials" class="mx-auto max-w-[1680px] px-6 pb-28 lg:px-14">
    <p data-reveal class="text-center text-sm uppercase tracking-wide">[Testimonials]</p>
    <% quotes = [
      ["1534528741775-53994a69daeb", "Homeowner", "Lisbon · 2025", "Before Velmora, our flat felt chopped up and smaller than it really was. We didn't want a big renovation, just something subtle, thoughtful and easy to live with."],
      ["1494790108377-be9c29b29330", "Café owner", "Porto · 2026", "Guests stay longer and come back more often. The room does half the hospitality for us, and we never had to explain what we wanted twice."],
      ["1438761681033-6461ffad8d80", "Studio founder", "Madrid · 2025", "They listened for two full days before drawing anything. Every corner of our new office now has a reason to exist."]
    ] %>
    <div data-tabs class="mx-auto mt-14 grid max-w-5xl gap-8 md:grid-cols-[80px_1fr]">
      <span class="text-8xl font-semibold leading-none" aria-hidden="true">&ldquo;</span>
      <div>
        <% quotes.each_with_index do |(image, role, meta, quote), index| %>
          <blockquote id="quote-<%= index %>" role="tabpanel" <%= "hidden" unless index.zero? %> class="text-2xl leading-snug md:text-4xl"><%= quote %></blockquote>
        <% end %>
        <div class="mt-8 flex flex-wrap items-center gap-3" role="tablist" aria-label="Choose a testimonial">
          <% quotes.each_with_index do |(image, role, meta, _quote), index| %>
            <button type="button" role="tab" aria-selected="<%= index.zero? %>" aria-controls="quote-<%= index %>" class="group flex items-center gap-3 rounded-full bg-stone p-1.5 transition aria-selected:pr-6">
              <img src="https://images.unsplash.com/photo-<%= image %>?auto=format&fit=crop&w=120&h=120&q=70" alt="<%= role %>" class="h-11 w-11 rounded-full object-cover">
              <span class="hidden text-left text-sm leading-tight group-aria-selected:block"><span class="block"><%= role %></span><span class="font-semibold"><%= meta %></span></span>
            </button>
          <% end %>
        </div>
      </div>
    </div>
  </section>
  <!-- block:end reviews -->
<script>
    document.querySelectorAll('[data-menu-toggle]').forEach((button) => {
      const menu = document.getElementById(button.getAttribute('aria-controls'));
      if (!menu) return;
      button.addEventListener('click', () => {
        const open = button.getAttribute('aria-expanded') === 'true';
        button.setAttribute('aria-expanded', String(!open));
        menu.classList.toggle('hidden', open);
      });
    });

    document.querySelectorAll('[data-tabs]').forEach((tabs) => {
      const buttons = tabs.querySelectorAll('[role="tab"]');
      buttons.forEach((button) => {
        button.addEventListener('click', () => {
          buttons.forEach((other) => {
            const active = other === button;
            other.setAttribute('aria-selected', String(active));
            document.getElementById(other.getAttribute('aria-controls')).hidden = !active;
          });
        });
      });
    });

    document.querySelectorAll('[data-accordion]').forEach((accordion) => {
      const buttons = accordion.querySelectorAll('[data-accordion-button]');
      buttons.forEach((button) => {
        button.addEventListener('click', () => {
          const open = button.getAttribute('aria-expanded') === 'true';
          buttons.forEach((other) => {
            other.setAttribute('aria-expanded', 'false');
            document.getElementById(other.getAttribute('aria-controls')).hidden = true;
          });
          button.setAttribute('aria-expanded', String(!open));
          document.getElementById(button.getAttribute('aria-controls')).hidden = open;
        });
      });
    });

    document.querySelectorAll('[data-filter-group]').forEach((group) => {
      const chips = group.querySelectorAll('[data-filter]');
      chips.forEach((chip) => {
        chip.addEventListener('click', () => {
          chips.forEach((other) => {
            const active = other === chip;
            other.setAttribute('aria-pressed', String(active));
            other.classList.toggle('bg-ink', active);
            other.classList.toggle('text-white', active);
          });
          document.querySelectorAll('[data-filter-item]').forEach((item) => {
            item.hidden = chip.dataset.filter !== 'all' && item.dataset.category !== chip.dataset.filter;
          });
        });
      });
    });

    document.querySelectorAll('[data-newsletter], [data-contact-form]').forEach((form) => {
      form.addEventListener('submit', (event) => {
        event.preventDefault();
        const status = form.querySelector('[data-form-status]');
        if (!form.checkValidity()) {
          status.textContent = form.dataset.error || 'Please enter a valid email address.';
          return;
        }
        status.textContent = form.dataset.success || 'Thank you! Your first letter is on its way.';
        form.reset();
      });
    });

    document.querySelectorAll('[data-current-year]').forEach((el) => { el.textContent = new Date().getFullYear(); });

    (() => {
      const items = document.querySelectorAll('[data-reveal]');
      const skip = navigator.webdriver || !('IntersectionObserver' in window) || matchMedia('(prefers-reduced-motion: reduce)').matches;
      if (!items.length || skip) return;
      document.documentElement.classList.add('reveal-ready');
      const observer = new IntersectionObserver((entries) => {
        entries.forEach((entry) => {
          if (!entry.isIntersecting) return;
          entry.target.classList.add('is-visible');
          observer.unobserve(entry.target);
        });
      }, { rootMargin: '0px 0px -10% 0px' });
      items.forEach((item) => observer.observe(item));
    })();
  </script>
</body>
</html>

From this template

Velmora screenshot

Agency

Velmora

Unlimited access to all products

Unlock the entire library of premium templates and blocks. Renews automatically, cancel anytime.

$20 / 3 months or $60 / year
Get Unlimited Access