跳到主要内容
返回画廊
FREE · 免费

Cybersecurity Hero

Heroheropage_type: hero2026-05-01

Build a single-page React + TypeScript (Vite) landing hero for a product called "Xero" that recreates the following section exactly. Use the Inter Google Font (weights 300, 400, 500, 600, 700, 800). Do not use Tailwind utility classes for the hero — write plain CSS in a global stylesheet. No purple/indigo branding outside the specified pink-magenta gradient arc.

Layout & Structure

Render three top-level blocks centered on a black page (#0a0a0f), each constrained to max-width: 1600px, in this vertical order:

  1. <nav> — sticky-style top bar (not actually sticky, just at top)
  2. <section class="hero-card"> — the rounded dark hero card with the animated icon pipeline
  3. <div class="brands"> — a row of 5 monochrome brand logos

The body uses display: flex; flex-direction: column; align-items: center; padding: 14px; and font-family: 'Inter', sans-serif;.

CSS Variables (on :root)

--bg: #0a0a0f;
--surface: #111118;
--text: #f0f0f5;
--text-muted: #8888a8;
--accent: #c8a0e0;
--accent-pink: #b04090;
--border: rgba(255, 255, 255, 0.08);

NAVBAR

  • Grid layout: grid-template-columns: 1fr auto 1fr; padding: 12px 24px; margin-bottom: 14px;
  • Left: <span class="nav-logo">Xero</span>font-size: 1.05rem; font-weight: 700; letter-spacing: -0.01em;
  • Center: <ul class="nav-links"> with three <a> items: Method, Pricing, Docs. Color --text-muted, font-size: 0.85rem, gap 32px, hover transitions to --text over 0.2s.
  • Right: <div class="nav-actions"> containing two pill buttons:
    • .btn-loginrgba(255,255,255,0.06) bg, 1px border --border, white text, padding 7px 18px, border-radius: 999px, font-size: 0.82rem, font-weight: 500. Hover: bg rgba(255,255,255,0.12).
    • .btn-signup — solid white bg, black #0a0a0f text, same dimensions, font-weight: 600. Hover: opacity: 0.88.
  • The .nav-menu wrapper uses display: contents on desktop so the ul and actions become direct grid children.

Mobile (≤ 768px)

  • Nav becomes flex with space-between.
  • A .menu-toggle hamburger appears: 24×14 button with two 2px-tall white spans. When .active, span 1 rotates translateY(6px) rotate(45deg) and span 2 rotates translateY(-6px) rotate(-45deg) to form an X.
  • .nav-menu.active slides in from right: -100% to right: 0 over 0.4s cubic-bezier(0.4, 0, 0.2, 1) as a full-screen var(--bg) overlay with column-stacked links and full-width buttons.
  • Toggling sets document.body.style.overflow = 'hidden'.

HERO CARD

Outer .hero-card styles:

  • width: 100%; max-width: 1600px; border-radius: 20px; border: 1px solid rgba(255,255,255,0.07); overflow: hidden; position: relative; background: #0d0b12; padding: 80px 40px 70px; min-height: 640px;
  • display: flex; flex-direction: column; align-items: center; text-align: center;

::before Gradient Arc (the signature visual)

A radial gradient positioned at 50% -70% with many manually-tuned stops producing a smooth dark→pink→white arc near the top:

background:
  radial-gradient(circle at 50% -70%,
    transparent 60%,
    rgba(176,48,136,0.03) 63%,
    rgba(176,48,136,0.08) 65%,
    rgba(176,48,136,0.16) 67%,
    rgba(176,48,136,0.28) 69%,
    rgba(176,48,136,0.40) 71%,
    rgba(176,48,136,0.52) 73%,
    rgba(176,48,136,0.64) 75%,
    rgba(176,48,136,0.74) 77%,
    rgba(176,48,136,0.82) 79%,
    rgba(210,70,175,0.92) 85%,
    rgba(240,110,210,0.88) 87%,
    rgba(255,205,250,0.92) 91%,
    rgba(255,240,255,0.98) 93%,
    #ffffff 95%),
  radial-gradient(circle at 50% 35%, rgba(120,40,180,0.08) 0%, transparent 50%);
z-index: 0; pointer-events: none;

.hero-grid Overlay

A separate absolutely-positioned div with crosshatch grid:

background-image:
  linear-gradient(rgba(255,255,255,0.07) 1px, transparent 1px),
  linear-gradient(90deg, rgba(255,255,255,0.07) 1px, transparent 1px);
background-size: 40px 40px;
mask-image: radial-gradient(circle at 50% -70%, transparent 60%, black 78%);

This makes the grid only visible inside the arc area.

ICON PIPELINE (the animated centerpiece)

Container .icon-pipeline: position: relative; display: flex; align-items: center; justify-content: center; max-width: 700px; margin-bottom: 52px; z-index: 1;

Children in this exact order:

  1. <svg class="beam-svg"> — absolutely-positioned over the whole pipeline (overflow: visible), containing:

    • A <filter id="glow"> with feGaussianBlur stdDeviation="2" then feComposite ... operator="over".
    • A <linearGradient id="beam-gradient" gradientUnits="userSpaceOnUse"> with stops:
      • 0% #b04090 opacity 0
      • 20% #b04090 opacity 0.8
      • 50% #fff opacity 1
      • 80% #c8a0e0 opacity 0.8
      • 100% #c8a0e0 opacity 0
    • Two <path> elements both stroked with url(#beam-gradient):
      • Glow path: stroke-width="2", filter="url(#glow)", opacity: 0.6.
      • Core path: stroke-width="0.8".
  2. Left node .icon-node.node-light-right (id node-stack) — Lucide-style layers SVG (3 stacked diamonds): <polygon points="12 2 2 7 12 12 22 7 12 2"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/>.

  3. .pipeline-linewidth: 160px; height: 1px; linear gradient 90deg, rgba(255,255,255,0.15), rgba(255,255,255,0.07).

  4. Center wrapper with position: relative; containing:

    • .splash — 100×100 absolutely centered, border-radius: 50%, background: radial-gradient(circle, rgba(255,77,200,0.6) 0%, transparent 70%), initial opacity: 0; transform: scale(0.4); z-index: 2;
    • .icon-node-center (id node-x) — 64×64 round, background: #1e1e2c, neumorphic shadow (see below), containing the Xero "X" logoipsum SVG (viewBox="0 0 40 40") — the multi-cut path provided in the source.
  5. .pipeline-line.right — same 160×1 line, gradient reversed.

  6. Right node .icon-node.node-light-left (id node-shield) — Lucide-style shield-check SVG: <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><polyline points="9 12 11 14 15 10"/>.

Side Node Styling

.icon-node: 46×46 round, background: #1a1a24, cursor: pointer, z-index: 3, with neumorphic shadow stack:

box-shadow:
  6px 6px 12px rgba(0,0,0,0.4),
  -4px -4px 10px rgba(255,255,255,0.03),
  inset 1px 1px 1px rgba(255,255,255,0.05),
  inset 4px 4px 8px rgba(0,0,0,0.4);

Plus an ::after dotted outer ring at inset: -7px (border: 1px dotted #1a1a24). Hover: translateY(-1px) and stronger shadows. Active: inset-only shadows. Inner SVG: 20×20, stroke rgba(255,255,255,0.7), stroke-width: 1.5, fill none, round caps.

Center Node Styling

.icon-node-center: 64×64, background: #1e1e2c, similar but stronger neumorphic shadow:

8px 8px 16px rgba(0,0,0,0.5),
-6px -6px 14px rgba(255,255,255,0.04),
inset 1px 1px 2px rgba(255,255,255,0.06),
inset 6px 6px 12px rgba(0,0,0,0.5);

Inner Xero SVG: 28×28, fill: white.

Side-Light Glows

  • .node-light-right::before — half-circle radial glow on the right side: radial-gradient(circle at right, rgba(200,200,200,0.45) 0%, transparent 70%), opacity: 0 default, opacity: 1 when .active (300ms transition).
  • .node-light-left::before — same but on left, color rgba(200,100,255,0.5).

Splash Keyframe

@keyframes splash-anim {
  0%   { transform: scale(0.4); opacity: 0.8; }
  40%  { opacity: 0.6; }
  100% { transform: scale(1.4); opacity: 0; }
}

Triggered by adding .animate (0.8s ease-out forwards).

BEAM ANIMATION (JavaScript / requestAnimationFrame)

Implement a state machine with four phases. On mount and on every window resize, recompute the SVG path:

const pRect = pipeline.getBoundingClientRect();
const sRect = nodeStack.getBoundingClientRect();
const xRect = nodeX.getBoundingClientRect();
const shRect = nodeShield.getBoundingClientRect();
const startX = sRect.left + sRect.width/2 - pRect.left;
const startY = sRect.top  + sRect.height/2 - pRect.top;
// midX/midY from nodeX, endX/endY from nodeShield
const d = `M ${startX},${startY} L ${midX},${midY} L ${endX},${endY}`;

Set this d on both beam paths.

The gradient is animated by mutating x1 / x2 of #beam-gradient (in userSpaceOnUse) so the bright window slides along. Use halfWidth = 5 (percentage units), center = percentage * 100:

gradient.x1 = (center - 5) + '%'
gradient.x2 = (center + 5) + '%'
y1 = y2 = '0%'

State machine in a requestAnimationFrame loop, tracking lastStateChange timestamp:

StateDurationBehavior
p1800 mspercentage interpolates 0 → 0.5. While p < 0.4, add .active to node-stack; remove after. At end: switch to splash, hide both beam paths (opacity: 0), add .animate to splash.
splash800 msWait. After elapsed: switch to p2, remove .animate, restore opacity: 1 on both beam paths.
p2800 mspercentage interpolates 0.5 → 1.0. While p > 0.6, add .active to node-shield. At end: remove .active, switch to idle.
idle1000 msWait, then loop back to p1.

Total cycle ≈ 3.4 seconds, infinite.

HERO TEXT

.hero-content max-width: 620px; z-index: 1;

<h1 class="hero-heading">
  The simple way
  <strong>encryption your data</strong>
</h1>
<p class="hero-sub">
  Fully managed data encrypting service and annotation<br>
  platform for teams of all industries.
</p>
<a href="#" class="btn-cta">Get Started</a>
  • .hero-heading: font-size: clamp(2.4rem, 5.5vw, 4rem); font-weight: 300; line-height: 1.1; letter-spacing: -0.02em;
  • .hero-heading strong: display: block; font-weight: 400; margin-top: 4px; with background: linear-gradient(to right, #ffffff, #a98597); -webkit-background-clip: text; -webkit-text-fill-color: transparent;
  • .hero-sub: 0.9rem, rgba(255,255,255,0.4), max-width: 440px, margin: 0 auto 36px.
  • .btn-cta: white pill, black text, padding: 12px 32px; border-radius: 999px; font-weight: 600;. Hover: opacity: 0.9; translateY(-1px).

BRANDS ROW

.brands: flex row, gap: 64px; padding: 32px 24px 10px; flex-wrap: wrap; justify-content: center;

Five .brand-item blocks (each: flex, gap 10, color rgba(255,255,255,0.35), font-size 1.1rem, font-weight 500, white-space nowrap, with a 22×22 SVG):

  1. Expedia<circle cx=12 cy=12 r=10 fill=current /><path fill="var(--bg)" d="M8 9h8v2H8zm0 4h6v2H8z"/> then text Expedia.
  2. asana — three filled circles: (12,7,r=4), (5,16,r=3.5), (19,16,r=3.5), text asana.
  3. zenefits — three stroked horizontal polylines (lengths 16/8/16) at y=8/12/16, text zenefits.
  4. HubSpot — small filled circle (15.5,8.5,r=2.5), stroked circle (8.5,8.5,r=2), paths connecting them; text HubSp<span class="hubspot-dot"></span>t where .hubspot-dot is a 6×6 round superscript dot.
  5. loom — circle (12,12,r=9) plus vertical/horizontal/diagonal stroke lines forming a globe-with-X, text loom.

Responsive Breakpoints

  • ≤ 860px: pipeline gap: 0; margin-bottom: 40px; .pipeline-line { width: 80px }.
  • ≤ 768px: enable mobile hamburger menu, .icon-node shrinks to 38×38, .icon-node-center to 52×52, .hero-card { padding: 60px 20px 60px; min-height: auto }, .brands { gap: 32px }.
  • ≤ 480px: .hero-card { border-radius: 16px }, .brands { gap: 24px }.

Z-Index Stack (critical for splash/beam layering)

  • 0 — gradient arc + grid overlay
  • 1 — pipeline container, hero text
  • 2 — beam SVG, splash
  • 3 — all icon nodes
  • 4 — node side-light glows
  • 1000-1001 — mobile nav overlay and toggle

Implement all of the above exactly. Use useRef for the pipeline, the three nodes, both beam paths, the gradient, and the splash. Use one useEffect to set up the resize listener and the requestAnimationFrame loop, and clean both up on unmount.