Free
About
Emberlyn About
A about block extracted from the Emberlyn template, available in Tailwind CSS and Bootstrap.
0
3
A about block extracted from the Emberlyn 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>Emberlyn About | Tailwind CSS UI Block</title>
<meta name="description" content="A about block extracted from the Emberlyn template, available in Tailwind CSS and Bootstrap.">
<meta name="keywords" content="Emberlyn, Tailwind CSS template, HTML website template, portfolio template, wedding photographer website, photography portfolio, elopement photographer, photo studio template, editorial portfolio">
<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="Emberlyn | Tailwind CSS Portfolio Template">
<meta property="og:description" content="A quiet, editorial Tailwind CSS portfolio template for wedding photographers, with a black-and-white hero slider, a staggered journal and a date availability calendar.">
<meta property="og:image" content="">
<meta property="og:image:alt" content="Emberlyn template preview">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:url" content="">
<meta name="twitter:title" content="Emberlyn | Tailwind CSS Portfolio Template">
<meta name="twitter:description" content="A quiet, editorial Tailwind CSS portfolio template for wedding photographers, with a black-and-white hero slider, a staggered journal and a date availability calendar.">
<meta name="twitter:image" content="">
<meta name="twitter:image:alt" content="Emberlyn 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=Cormorant+Garamond:wght@400;500;600&family=Mrs+Saint+Delafield&family=Playfair+Display:wght@400;500&family=Poppins:wght@300;400;500&display=swap" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: { paper: '#f7f6f2', sand: '#efede8', sage: { DEFAULT: '#5f6c5f', deep: '#4b564b' }, ink: '#232323', mute: '#707070' },
fontFamily: { sans: ['Poppins', 'sans-serif'], serif: ['Playfair Display', 'serif'], caps: ['Cormorant Garamond', 'serif'], script: ['Mrs Saint Delafield', 'cursive'] }
}
}
}
</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; }
.slide { transition: opacity .7s ease, transform 6s ease; }
.slide:not(.is-active) { opacity: 0; }
.slide.is-active { transform: scale(1.04); }
.notch { clip-path: polygon(0 0, 100% 0, 100% calc(100% - 1.25rem), calc(50% + 1.25rem) calc(100% - 1.25rem), 50% 100%, calc(50% - 1.25rem) calc(100% - 1.25rem), 0 calc(100% - 1.25rem)); }
.reveal-ready [data-reveal] { opacity: 0; transform: translateY(24px); transition: opacity .7s ease, transform .7s 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; }
.slide { transition: none; }
.slide.is-active { transform: none; }
::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}
</style>
</head>
<body class="bg-paper font-sans font-light text-ink antialiased">
<% active_page = "index" %>
<% left_nav = { "about" => "meet us", "story" => "our story", "services" => "services" } %>
<% right_nav = { "portfolio" => "portfolio", "blog" => "the journal", "contact" => "hire us" } %>
<% left_nav.each do |slug, label| %>
<% active = active_page == slug %>
<% end %>
<% right_nav.each do |slug, label| %>
<% active = active_page == slug %>
<% end %>
<% { "index" => "home" }.merge(left_nav).merge(right_nav).each do |slug, label| %>
<% active = active_page == slug %>
<% end %>
<% slides = [["1460978812857-470ed1c77af0", "Couple kissing on a windy shore, the bride's veil lifting in black and white"], ["1537633552985-df8429e8048b", "Bride and groom embracing by the sea, her long veil trailing on the pebbles"], ["1532712938310-34cb3982ef74", "Newlyweds walking hand in hand across a hilltop at dusk"]] %>
<% slides.each_with_index do |(photo, alt), index| %>
<% end %>
<% slides.each_index do |index| %>
<% end %>
<% [["fa-instagram", "Instagram", "https://www.instagram.com"], ["fa-facebook-f", "Facebook", "https://www.facebook.com"], ["fa-pinterest-p", "Pinterest", "https://www.pinterest.com"]].each do |icon, label, url| %>
<% end %>
<!-- block:start about -->
<section id="welcome" class="relative">
<div class="mx-auto h-24 w-px bg-ink/60 md:h-28" aria-hidden="true"></div>
<p class="mx-auto max-w-3xl px-6 pb-20 pt-12 text-center font-caps text-base font-medium uppercase leading-relaxed tracking-[0.25em] md:pb-28 md:text-lg" data-reveal>
We exist to share the joy of a celebration. Every story we tell is shaped around yours: tender or playful, wild or quietly classic. We look after every small detail so you can stay inside the moments that matter.
</p>
<div class="relative">
<div class="absolute inset-x-0 bottom-0 top-28 bg-white md:top-36" aria-hidden="true"></div>
<div class="relative mx-auto grid max-w-6xl gap-10 px-5 pb-20 md:grid-cols-[0.8fr_1fr] md:gap-16 md:px-10 md:pb-28">
<img src="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?auto=format&fit=crop&w=900&q=80" alt="Portrait of photographer Elias Marlowe in black and white" class="aspect-[3/4] w-full object-cover grayscale" loading="lazy" data-reveal>
<div class="md:pt-6">
<h2 class="font-script text-6xl leading-none md:text-8xl">Hi, I'm Elias</h2>
<div class="relative mt-16 border-l border-ink/60 pb-10 pl-8 md:ml-10 md:mt-24 md:pl-12">
<p class="max-w-md text-sm leading-[2] text-ink/80">For ten years I worked in newsrooms, chasing deadlines across three countries. A friend's wedding in Porto changed the plan: I came home with four hundred photos and a new job. Today I photograph around thirty weddings a year, mostly couples who want honest pictures that still feel like them in thirty years.</p>
<a href="contact.html" class="absolute -bottom-5 -left-5 bg-sage px-9 py-3 text-[11px] uppercase tracking-[0.4em] text-white transition hover:bg-sage-deep md:-left-14">Contact</a>
</div>
</div>
</div>
</div>
</section>
<!-- block:end about -->
<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-slider]').forEach((slider) => {
const slides = [...slider.querySelectorAll('[data-slide]')];
const dots = [...slider.querySelectorAll('[data-slider-dot]')];
let current = 0;
let timer;
const show = (index) => {
current = (index + slides.length) % slides.length;
slides.forEach((slide, i) => {
slide.classList.toggle('is-active', i === current);
slide.toggleAttribute('aria-hidden', i !== current);
});
dots.forEach((dot, i) => dot.setAttribute('aria-pressed', String(i === current)));
};
const restart = () => {
clearInterval(timer);
if (!matchMedia('(prefers-reduced-motion: reduce)').matches) timer = setInterval(() => show(current + 1), 6000);
};
slider.querySelector('[data-slider-prev]')?.addEventListener('click', () => { show(current - 1); restart(); });
slider.querySelector('[data-slider-next]')?.addEventListener('click', () => { show(current + 1); restart(); });
dots.forEach((dot, i) => dot.addEventListener('click', () => { show(i); restart(); }));
restart();
});
document.querySelectorAll('[data-carousel]').forEach((carousel) => {
const slides = [...carousel.querySelectorAll('[data-carousel-slide]')];
const index = carousel.querySelector('[data-carousel-index]');
let current = 0;
const show = (next) => {
current = (next + slides.length) % slides.length;
slides.forEach((slide, i) => { slide.hidden = i !== current; });
if (index) index.textContent = current + 1;
};
carousel.querySelector('[data-carousel-prev]')?.addEventListener('click', () => show(current - 1));
carousel.querySelector('[data-carousel-next]')?.addEventListener('click', () => show(current + 1));
});
document.querySelectorAll('[data-hover-list]').forEach((list) => {
const preview = list.querySelector('[data-hover-preview]');
if (!preview || !matchMedia('(hover: hover)').matches) return;
list.querySelectorAll('[data-hover-item]').forEach((item) => {
item.addEventListener('mouseenter', () => { preview.src = item.dataset.image; preview.style.opacity = '1'; });
item.addEventListener('mouseleave', () => { preview.style.opacity = '0'; });
item.addEventListener('mousemove', (event) => { preview.style.transform = `translate(${event.clientX + 28}px, ${event.clientY - 90}px) rotate(-3deg)`; });
});
});
document.querySelectorAll('[data-availability]').forEach((root) => {
const months = [...root.querySelectorAll('[data-month]')];
const label = root.querySelector('[data-month-label]');
const prev = root.querySelector('[data-month-prev]');
const next = root.querySelector('[data-month-next]');
const summary = root.querySelector('[data-availability-summary]');
const note = root.querySelector('[data-availability-note]');
let current = 0;
const showMonth = (index) => {
current = Math.max(0, Math.min(months.length - 1, index));
months.forEach((month, i) => { month.hidden = i !== current; });
label.textContent = months[current].dataset.month;
prev.disabled = current === 0;
next.disabled = current === months.length - 1;
};
prev.addEventListener('click', () => showMonth(current - 1));
next.addEventListener('click', () => showMonth(current + 1));
root.addEventListener('click', (event) => {
const day = event.target.closest('[data-day]');
if (!day || day.disabled) return;
root.querySelectorAll('[data-day]').forEach((other) => other.setAttribute('aria-pressed', String(other === day)));
summary.textContent = `${day.dataset.day} is free`;
note.textContent = 'Lovely choice. Hold it now and I will keep it for you for seven days.';
});
showMonth(0);
});
document.querySelectorAll('[data-filter-group]').forEach((group) => {
const items = document.querySelectorAll(group.dataset.filterGroup);
group.querySelectorAll('[data-filter]').forEach((chip) => {
chip.addEventListener('click', () => {
group.querySelectorAll('[data-filter]').forEach((other) => other.setAttribute('aria-pressed', String(other === chip)));
items.forEach((item) => { item.hidden = chip.dataset.filter !== 'all' && item.dataset.role !== chip.dataset.filter; });
});
});
});
document.querySelectorAll('[data-lightbox]').forEach((dialog) => {
const image = dialog.querySelector('img');
const caption = dialog.querySelector('[data-lightbox-caption]');
document.querySelectorAll('[data-lightbox-open]').forEach((button) => {
button.addEventListener('click', () => {
image.src = button.dataset.full;
image.alt = button.querySelector('img')?.alt || '';
caption.textContent = button.dataset.caption;
dialog.showModal();
});
});
dialog.addEventListener('click', (event) => { if (event.target === dialog) dialog.close(); });
});
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]');
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>
Portfolio
Unlock the entire library of premium templates and blocks. Renews automatically, cancel anytime.