Free
Call to action
Kindhire Call to action
A call to action block extracted from the Kindhire template, available in Tailwind CSS and Bootstrap.
0
1
A call to action block extracted from the Kindhire template, available in Tailwind CSS and Bootstrap.
<!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>Kindhire Call to action | Tailwind CSS UI Block</title>
<meta name="description" content="A call to action block extracted from the Kindhire template, available in Tailwind CSS and Bootstrap.">
<meta name="keywords" content="Kindhire, Tailwind CSS template, HTML website template, business template, inclusive hiring, accessible job board, disability employment, recruitment platform, remote jobs website, employer page">
<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="Kindhire | Tailwind CSS Business Template">
<meta property="og:description" content="A warm, accessible Tailwind CSS business template for inclusive hiring platforms, with arch portraits, a story carousel and a live job matcher.">
<meta property="og:image" content="">
<meta property="og:image:alt" content="Kindhire template preview">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:url" content="">
<meta name="twitter:title" content="Kindhire | Tailwind CSS Business Template">
<meta name="twitter:description" content="A warm, accessible Tailwind CSS business template for inclusive hiring platforms, with arch portraits, a story carousel and a live job matcher.">
<meta name="twitter:image" content="">
<meta name="twitter:image:alt" content="Kindhire template preview">
<script src="https://cdn.tailwindcss.com/3.4.17"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,700;9..144,800&family=Urbanist:wght@400;500;600;700&display=swap" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: { paper: '#f4f4f2', ink: '#141414', royal: { DEFAULT: '#0b4ea2', dark: '#083a7a', soft: '#dfe9f7' }, coral: { DEFAULT: '#f4846a', soft: '#fde3dc' }, leaf: { DEFAULT: '#3aa52a', soft: '#dff1db' }, sun: '#ffc928' },
fontFamily: { sans: ['Urbanist', 'sans-serif'], serif: ['Fraunces', '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; } }
html { scroll-behavior: smooth; }
[hidden] { display: none !important; }
.wiggle { animation: wiggle 5s ease-in-out infinite; transform-origin: center; }
@keyframes wiggle { 50% { rotate: 6deg; } }
.logos { animation: logos 34s linear infinite; }
.logos:hover { animation-play-state: paused; }
@keyframes logos { to { transform: translateX(-50%); } }
.ring-fill { transition: stroke-dashoffset .7s ease; }
.timeline-fill { transform-origin: top; }
.story { transition: opacity .4s ease; }
.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; }
.wiggle, .logos { animation: none; }
.ring-fill, .story { transition: none; }
::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}
</style>
</head>
<body class="bg-paper font-sans text-ink antialiased">
<% active_page = "index" %>
<% nav = { "platform" => "Platform", "jobs" => "Jobs", "employers" => "For employers", "stories" => "Stories", "about" => "About", "contact" => "Contact" } %>
<% { "index" => "Home" }.merge(nav).each do |slug, label| %>
<% active = active_page == slug %>
<% end %>
<% arches = [["1507003211169-0a1dd7228f2d", "Smiling man in a white T-shirt", "Marco", "QA tester", "bg-royal", "halo", "lg:mt-0"], ["1580489944761-15a19d654956", "Smiling woman with her hair tied up", "Lina", "web designer", "bg-coral", "burst", "lg:mt-36"], ["1599566150163-29194dcaad36", "Young man with glasses and a beard", "Sam", "content moderator", "bg-leaf", "zigzag", "lg:mt-0"]] %>
<% arches.each_with_index do |(photo, alt, name, role, color, doodle, offset), index| %>
<% if index == 1 %>
<% end %>
<% if doodle == "halo" %>
<% elsif doodle == "burst" %>
<% else %>
<% end %>
<% unless index == 1 %>
<% else %>
<% end %>
<% end %>
<% stories = [["Elena Ruiz", "38, works from Lisbon, uses a wheelchair", "Moderating content is calm, focused work, and I can split my hours however my body needs. Two hours in the morning, two in the evening. My team checks in, never checks up.", "1573497019940-1c28c88b4f3e", "bg-royal"], ["Daniel Okafor", "29, works from Leeds, hard of hearing", "Every meeting has live captions and everything important is written down. For the first time I'm judged on my work, not on how fast I catch what people say.", "1500648767791-00dcc994a43e", "bg-coral"], ["Mei Tanaka", "34, works from Osaka, chronic fatigue", "Flexible deadlines changed everything. I design on good days and rest on hard ones, and nobody makes me explain myself.", "1573497019236-17f8177b81e8", "bg-leaf"]] %>
<% stories.each_with_index do |(name, meta, quote, photo, color), index| %>
<% end %>
<% stories.each_with_index do |story, index| %>
<% end %>
<% skills = [["design", "Design"], ["writing", "Writing"], ["support", "Customer support"], ["testing", "Software testing"], ["data", "Data entry"], ["moderation", "Moderation"]] %>
<% needs = [["remote", "Fully remote", "fa-house-laptop"], ["flexible", "Flexible hours", "fa-clock"], ["captions", "Captioned meetings", "fa-closed-captioning"], ["reader", "Screen-reader friendly", "fa-universal-access"]] %>
<% jobs = [["Junior UI designer", "Brightfield Studio", "design", "remote flexible reader", "$38–44K", "bg-coral-soft"], ["Support specialist", "Parcelpoint", "support", "remote captions flexible", "$32–36K", "bg-royal-soft"], ["QA tester", "Northgate Apps", "testing", "remote reader captions flexible", "$40–48K", "bg-leaf-soft"], ["Content moderator", "Openstream", "moderation", "remote flexible", "$30–34K", "bg-royal-soft"], ["Copywriter", "Hearthline", "writing", "remote flexible captions", "$36–42K", "bg-coral-soft"], ["Data assistant", "Clearpath Health", "data", "flexible reader", "$29–33K", "bg-leaf-soft"]] %>
<% skills.each_with_index do |(id, label), index| %>
<% end %>
<% needs.each_with_index do |(id, label, icon), index| %>
<% end %>
<% jobs.each do |title, company, skill, tags, salary, tone| %>
<% needs.each do |id, label, icon| %>
<% if tags.include?(id) %>
<% end %>
<% end %>
<% end %>
<% steps = [["Sign up in your own way", "Online, by phone, by text or over a sign language video call.", "fa-hand"], ["Free skills check", "A relaxed chat with a career coach about what you enjoy and what you need.", "fa-comments"], ["Paid training", "Six weeks of online training, paid from day one, at your own pace.", "fa-graduation-cap"], ["Your first role", "We introduce you to an employer who has already set up your accommodations.", "fa-briefcase"], ["Ongoing support", "A coach checks in every month for your first year, and more if you want.", "fa-heart"]] %>
<% steps.each_with_index do |(title, text, icon), index| %>
<% end %>
<% rings = [[92, "still in work after a year", "#0b4ea2"], [78, "work fully from home", "#f4846a"], [64, "promoted within two years", "#3aa52a"]] %>
<% rings.each do |value, label, color| %>
<% end %>
<% partners = [["fa-leaf", "Brightfield"], ["fa-box", "Parcelpoint"], ["fa-compass", "Northgate"], ["fa-water", "Openstream"], ["fa-fire", "Hearthline"], ["fa-heart-pulse", "Clearpath"], ["fa-mountain", "Highbank"]] %>
<% (partners + partners).each_with_index do |(icon, name), index| %>
<% end %>
<% faqs = [["Does it cost anything?", "No. Kindhire is free for job seekers, forever. Employers pay us when they hire."], ["What if I can only work a few hours?", "Plenty of our roles start at 10 hours a week. Tell us your limit and we'll respect it."], ["Will my benefits be affected?", "Our advisers help you check how earnings affect any support you receive before you accept an offer."], ["Can someone help me fill in the forms?", "Yes. A coach can do it with you over the phone, by video or by text."]] %>
<% faqs.each do |question, answer| %>
<% end %>
<!-- block:start cta -->
<section class="mx-auto max-w-7xl px-5 pb-24 md:px-10">
<div class="grid overflow-hidden rounded-[3rem] bg-coral lg:grid-cols-2">
<div class="p-8 md:p-14">
<h2 class="font-serif text-4xl font-bold leading-tight tracking-tight md:text-5xl">Start this week</h2>
<p class="mt-4 max-w-sm text-lg">Leave your email and a coach will call or text you, whichever you prefer.</p>
<form data-contact-form data-error="Please add a valid email." data-success="Thanks! A coach will be in touch within two working days." class="mt-8" novalidate>
<label for="cta-email" class="font-semibold">Email</label>
<div class="mt-2 flex flex-col gap-3 sm:flex-row">
<input id="cta-email" type="email" name="email" required autocomplete="email" placeholder="you@example.com" class="min-w-0 flex-1 rounded-full border-0 bg-white px-5 py-4 focus:outline-none focus:ring-4 focus:ring-royal">
<button type="submit" class="rounded-full bg-ink px-7 py-4 font-semibold text-white transition hover:bg-royal">Get started</button>
</div>
<p data-form-status class="mt-3 font-semibold" role="status" aria-live="polite"></p>
</form>
</div>
<img src="https://images.unsplash.com/photo-1521737604893-d14cc237f11d?auto=format&fit=crop&w=900&h=700&q=75" alt="Team of colleagues working together at a long table" class="h-full min-h-[18rem] w-full object-cover lg:rounded-l-full">
</div>
</section>
<!-- block:end cta -->
<script>
const reducedMotion = matchMedia('(prefers-reduced-motion: reduce)').matches;
const watchMotion = !reducedMotion && !navigator.webdriver && 'IntersectionObserver' in window;
document.querySelectorAll('[data-menu-toggle]').forEach((button) => {
const menu = document.getElementById(button.getAttribute('aria-controls'));
const close = menu.querySelector('[data-menu-close]');
const set = (open) => { menu.hidden = !open; button.setAttribute('aria-expanded', String(open)); document.body.style.overflow = open ? 'hidden' : ''; (open ? close : button).focus(); };
button.addEventListener('click', () => set(menu.hidden));
close.addEventListener('click', () => set(false));
document.addEventListener('keydown', (event) => { if (event.key === 'Escape' && !menu.hidden) set(false); });
});
document.querySelectorAll('[data-carousel]').forEach((root) => {
const slides = [...root.querySelectorAll('[data-slide]')];
const dots = [...root.querySelectorAll('[data-carousel-dot]')];
let current = 0;
const show = (index) => {
current = (index + slides.length) % slides.length;
slides.forEach((slide, i) => { slide.hidden = i !== current; });
dots.forEach((dot, i) => dot.setAttribute('aria-current', String(i === current)));
};
root.querySelectorAll('[data-carousel-prev]').forEach((button) => button.addEventListener('click', () => show(current - 1)));
root.querySelectorAll('[data-carousel-next]').forEach((button) => button.addEventListener('click', () => show(current + 1)));
dots.forEach((dot, i) => dot.addEventListener('click', () => show(i)));
root.addEventListener('keydown', (event) => { if (event.key === 'ArrowLeft') show(current - 1); if (event.key === 'ArrowRight') show(current + 1); });
});
document.querySelectorAll('[data-matcher]').forEach((root) => {
const jobs = [...root.querySelectorAll('[data-job]')];
const isOn = (el) => el.getAttribute('aria-pressed') === 'true' || el.selected === true || el.checked === true;
const paint = () => {
const skills = [...root.querySelectorAll('[data-skill]:not([data-job])')].filter(isOn).map((el) => el.dataset.skill);
const needs = [...root.querySelectorAll('[data-need]')].filter(isOn).map((el) => el.dataset.need);
let shown = 0;
jobs.forEach((job) => {
const match = (!skills.length || skills.includes(job.dataset.skill)) && needs.every((need) => job.dataset.needs.split(' ').includes(need));
job.hidden = !match;
if (match) shown += 1;
});
root.querySelector('[data-match-count]').textContent = shown;
root.querySelector('[data-match-empty]').hidden = shown > 0;
};
root.querySelectorAll('[data-skill]:not([data-job])').forEach((chip) => chip.addEventListener('click', () => { if (chip.hasAttribute('aria-pressed')) chip.setAttribute('aria-pressed', String(chip.getAttribute('aria-pressed') !== 'true')); requestAnimationFrame(paint); }));
root.addEventListener('change', paint);
if (window.customElements) customElements.whenDefined('md-filter-chip').then(() => requestAnimationFrame(paint));
paint();
});
document.querySelectorAll('[data-timeline]').forEach((root) => {
const fill = root.querySelector('[data-timeline-fill]');
if (!watchMotion) return;
const update = () => {
const box = root.getBoundingClientRect();
fill.style.transform = `scaleY(${Math.min(1, Math.max(0, (innerHeight * 0.6 - box.top) / box.height))})`;
};
update();
addEventListener('scroll', update, { passive: true });
});
document.querySelectorAll('[data-rings]').forEach((root) => {
const rings = root.querySelectorAll('[data-ring]');
if (!watchMotion) return;
rings.forEach((ring) => { ring.style.strokeDashoffset = 326.73; });
const observer = new IntersectionObserver((entries) => {
if (!entries.some((entry) => entry.isIntersecting)) return;
rings.forEach((ring) => { ring.style.strokeDashoffset = 326.73 * (1 - Number(ring.dataset.ring) / 100); });
observer.disconnect();
}, { threshold: 0.3 });
observer.observe(root);
});
document.querySelectorAll('[data-chat]').forEach((root) => {
const log = root.querySelector('[data-chat-log]');
const add = (text, mine) => {
const item = document.createElement('li');
item.className = mine ? 'ml-auto max-w-[85%] rounded-3xl rounded-br-md bg-royal px-5 py-3 text-white' : 'max-w-[85%] rounded-3xl rounded-bl-md bg-paper px-5 py-3';
item.textContent = text;
log.append(item);
log.scrollTop = log.scrollHeight;
};
root.querySelectorAll('[data-chat-question]').forEach((button) => button.addEventListener('click', () => {
add(button.dataset.label || button.textContent.trim(), true);
setTimeout(() => add(button.dataset.answer, false), reducedMotion ? 0 : 450);
}));
});
document.querySelectorAll('[data-hover-list]').forEach((root) => {
const image = root.querySelector('[data-hover-image]');
root.querySelectorAll('[data-hover-row]').forEach((row) => {
const show = () => { image.src = row.dataset.image; image.alt = row.dataset.alt; root.querySelectorAll('[data-hover-row]').forEach((other) => other.setAttribute('aria-current', String(other === row))); };
row.addEventListener('mouseenter', show);
row.addEventListener('focus', show);
row.addEventListener('click', show);
});
});
document.querySelectorAll('[data-job-board]').forEach((root) => {
const list = root.querySelector('[data-board-list]');
const items = [...list.children];
const search = root.querySelector('[data-board-search]');
const sort = root.querySelector('[data-board-sort]');
const apply = () => {
const query = String(search.value || '').trim().toLowerCase();
const sorted = [...items].sort((a, b) => sort.value === 'salary' ? b.dataset.salary - a.dataset.salary : sort.value === 'hours' ? a.dataset.hours - b.dataset.hours : b.dataset.date - a.dataset.date);
let shown = 0;
sorted.forEach((item) => { const match = !query || item.textContent.toLowerCase().includes(query); item.hidden = !match; if (match) shown += 1; list.append(item); });
root.querySelector('[data-board-count]').textContent = shown;
root.querySelector('[data-board-empty]').hidden = shown > 0;
};
search.addEventListener('input', apply);
sort.addEventListener('change', apply);
const initial = new URLSearchParams(location.search).get('q');
if (initial) search.value = initial;
apply();
});
document.querySelectorAll('[data-calculator]').forEach((root) => {
const money = (value) => `$${Math.round(value).toLocaleString('en-US')}`;
const paint = () => {
const hires = Number(root.querySelector('[data-hires]').value);
const salary = Number(root.querySelector('[data-salary]').value);
const fee = hires * salary * 0.08;
const credit = hires * Math.min(salary * 0.25, 9600);
root.querySelector('[data-hires-label]').textContent = hires;
root.querySelector('[data-salary-label]').textContent = money(salary);
root.querySelector('[data-fee]').textContent = money(fee);
root.querySelector('[data-credit]').textContent = `−${money(credit)}`;
root.querySelector('[data-net]').textContent = money(Math.max(0, fee - credit));
};
root.addEventListener('input', paint);
paint();
});
document.querySelectorAll('[data-chat-form]').forEach((form) => {
const log = form.querySelector('[data-chat-log]');
const steps = [...form.querySelectorAll('[data-chat-step]')];
const status = form.querySelector('[data-form-status]');
let current = 0;
const say = (text, mine) => {
const bubble = document.createElement('li');
bubble.className = mine ? 'ml-auto max-w-[85%] rounded-3xl rounded-br-md bg-royal px-5 py-3 text-white' : 'max-w-[85%] rounded-3xl rounded-bl-md bg-paper px-5 py-3';
bubble.textContent = text;
log.append(bubble);
log.scrollTop = log.scrollHeight;
};
const show = (index) => steps.forEach((step, i) => { step.hidden = i !== index; });
const field = (step) => step.querySelector('input, select, textarea, md-outlined-text-field, md-outlined-select');
form.addEventListener('submit', (event) => {
event.preventDefault();
const input = field(steps[current]);
if (!input.checkValidity() || !String(input.value || '').trim()) { status.textContent = form.dataset.error; input.focus(); return; }
status.textContent = '';
say(String(input.value), true);
current += 1;
if (current < steps.length) { say(steps[current].dataset.question, false); show(current); field(steps[current]).focus(); }
else { say(form.dataset.success, false); show(-1); }
});
show(0);
});
document.querySelectorAll('[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;
form.querySelector(':invalid')?.focus();
return;
}
status.textContent = form.dataset.success;
form.reset();
});
});
document.querySelectorAll('[data-current-year]').forEach((el) => { el.textContent = new Date().getFullYear(); });
(() => {
const items = document.querySelectorAll('[data-reveal]');
if (!items.length || !watchMotion) 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>
Business
Unlock the entire library of premium templates and blocks. Renews automatically, cancel anytime.