Skip to content

Tailwind hover effects in plain HTML and CSS

Everything, with no framework at all. An effect is a class and its rules; a block is its rendered markup. Nothing to install and nothing to hydrate.

  • Rails
  • Laravel
  • Django
  • Phoenix
  • Hugo
  • no build step at all

An effect, in HTML + CSS

This is the Gradient Shift Button effect, run through the converter when this page was built — not a sample of what the output is meant to look like. All 1,126 effects convert the same way, because every one of them is markup plus a stylesheet.

btn-gradient.html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Gradient Shift Button — Hoverlab</title>
  <style>
    .fx-btn-gradient {
      position: relative;
      padding: 0.75rem 1.75rem;
      border: none;
      border-radius: 0.625rem;
      font-weight: 600;
      font-size: 0.95rem;
      color: #fff;
      cursor: pointer;
      background: linear-gradient(120deg, #f43f5e, #f59e0b, #10b981, #6366f1);
      background-size: 300% 300%;
      background-position: 0% 50%;
      transition: background-position 0.6s ease, transform 0.2s ease, box-shadow 0.3s ease;
      box-shadow: 0 6px 18px -6px rgba(244, 63, 94, 0.5);
    }
    .fx-btn-gradient:hover {
      background-position: 100% 50%;
      transform: translateY(-2px);
      box-shadow: 0 12px 28px -8px rgba(99, 102, 241, 0.55);
    }
    .fx-btn-gradient:active { transform: translateY(0); }
  </style>
</head>
<body>
  <button class="fx-btn-gradient">Get Started</button>
</body>
</html>

A block, as a HTML + CSS file

This is where the honest answer is different, so here it is with the words that make it different. 433 blocks and pages are React components with state and handlers. What you get in HTML + CSS is the block rendered to markup and wrapped as a file your framework compiles — a real presentational component, carrying the layout, the Tailwind classes and the accessible structure, and not a port of the React logic.

The sample below is Magic Link Sign In, and it is an interactive one, chosen so you can see exactly what is missing rather than a case where nothing is. The caveat is printed at the top of the file itself, because the file is what gets read six months later.

auth-magic-link-form.html
<!--
  Magic Link Sign In — markup from the Hoverlab catalog.

  This is the block rendered once to HTML and wrapped as a component
  file. It is not a port of the React source: the Tailwind classes carry
  the design, which is the part that took the work, and they are the same
  in every framework.

  This block is interactive in React and the handlers are NOT here.
  Buttons, toggles and menus render in their initial state and do
  nothing until you wire them up.
-->
<section aria-labelledby="_R_0_-auth-magic-link-form-heading" class="w-full bg-background px-6 py-16 ">
  <div class="mx-auto max-w-md rounded-xl border border-border bg-card p-8 shadow-sm">
    <h2 id="_R_0_-auth-magic-link-form-heading" class="text-xl font-semibold tracking-tight text-card-foreground">Sign in without a password</h2>
    <p class="mt-2 text-sm text-muted-foreground">One address, one link, no password to forget or reuse. The link works once and expires in fifteen minutes, which is stated here rather than discovered when it fails.</p>
    <form class="mt-6 space-y-4">
      <div>
        <label for="_R_0_-auth-magic-link-form-email" class="block text-sm font-medium text-foreground">Email</label>
        <input id="_R_0_-auth-magic-link-form-email" type="email" required="" aria-describedby="_R_0_-auth-magic-link-form-email-hint" class="mt-1.5 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring" name="email" />
        <p id="_R_0_-auth-magic-link-form-email-hint" class="mt-1 text-xs text-muted-foreground">The link lands here and works once. It expires after 15 minutes.</p>
      </div>
      <button type="submit" class="w-full rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-60">Email me a link</button>
      <p role="status" aria-live="polite" class="min-h-5 text-sm text-muted-foreground"></p>
    </form>
  </div>
</section>

Getting it into your project

terminal
npx hoverlab add btn-gradient

In a monorepo where detection has nothing to go on, say it outright: npx hoverlab add btn-gradient --framework html

For the block markup, the API

The CLI’s framework flag covers effects; it writes blocks as their React source. The markup wrapper comes from the public API instead — no key, no account:

terminal
curl "https://hoverlab5.netlify.app/api/v1/blocks/auth-magic-link-form?format=html&framework=html"
  1. Paste the markup into your template. Server-rendered templates in Rails, Laravel, Django and Phoenix take it unchanged — it is HTML with Tailwind classes.
  2. Either keep the <style> block where it is or move the rules into your stylesheet. Nothing here depends on where it lives.
  3. No build step, no install, nothing to hydrate.

Where the licence comes into it

HTML + CSS output is not gated anywhere — not in the export panel, not in the API, not in the CLI. What Pro sells is the licence to ship it, which is a separate question from reaching it.

Also targeted