Open demo

CSS code

HTML
<section class="cv" aria-labelledby="cv-title">
  <h2 id="cv-title">Experience</h2>
  <p class="sub">A two-column CV timeline — dates left, story right.</p>
  <ol>
    <li>
      <p class="when"><b><time datetime="2024">2024</time> — now</b>Berlin</p>
      <div class="what"><h3>Staff Product Designer</h3><p class="org">Meridian</p><p>Own the design system and the analytics surface used by 28k teams. Halved onboarding drop-off by redesigning the first-run flow.</p><ul class="skills" aria-label="Skills"><li>Design systems</li><li>Prototyping</li><li>Research</li></ul></div>
    </li>
    <li>
      <p class="when"><b><time datetime="2021">2021</time> — <time datetime="2024">2024</time></b>Remote</p>
      <div class="what"><h3>Senior Designer</h3><p class="org">Fieldnote</p><p>First design hire. Took the product from beta to 40k users and built the component library that outlived my tenure.</p><ul class="skills" aria-label="Skills"><li>Product design</li><li>Frontend</li></ul></div>
    </li>
    <li>
      <p class="when"><b><time datetime="2018">2018</time> — <time datetime="2021">2021</time></b>Porto</p>
      <div class="what"><h3>UI Designer</h3><p class="org">Studio Norte</p><p>Client work across fintech and culture — twelve shipped sites, two industry awards, one very patient art director.</p><ul class="skills" aria-label="Skills"><li>Branding</li><li>Web design</li></ul></div>
    </li>
  </ol>
</section>
CSS
/* Two-column CV timeline: dates on the left, the role on the right, a rail and dot between them.
   Under 560px the columns stack and the rail is dropped. */
.cv{--cv-accent:#b45309;--cv-line:#eae7df;--cv-muted:#706a5d;--cv-text:#5a544a;
  box-sizing:border-box;width:100%;max-width:640px;background:#fff;border:1px solid var(--cv-line);border-radius:16px;padding:40px 44px;
  box-shadow:0 16px 38px -24px rgba(60,50,30,.25)}
.cv>h2{margin:0;font-size:1.25rem;letter-spacing:-.01em}
.cv .sub{color:var(--cv-muted);font-size:.88rem;margin:4px 0 34px}
.cv>ol{margin:0;padding:0;list-style:none}
.cv>ol>li{display:grid;grid-template-columns:130px 1fr;gap:0 26px;position:relative;padding-bottom:32px}
.cv>ol>li:last-child{padding-bottom:0}
.cv>ol>li::before{content:"";position:absolute;left:146px;top:6px;bottom:-6px;width:2px;background:var(--cv-line)}
.cv>ol>li:last-child::before{bottom:auto;height:calc(100% - 6px)}
.cv>ol>li::after{content:"";position:absolute;left:141px;top:6px;box-sizing:border-box;width:12px;height:12px;border-radius:50%;background:var(--cv-accent);border:3px solid #fdf6ec}
.cv .when{margin:0;text-align:right;font-size:.78rem;font-weight:700;color:var(--cv-muted);padding-top:2px;line-height:1.5}
.cv .when b{display:block;color:var(--cv-accent);font-size:.8rem}
.cv .what{padding-left:16px}
.cv h3{margin:0 0 2px;font-size:1rem}
.cv .org{margin:0 0 8px;font-size:.83rem;font-weight:600;color:var(--cv-muted)}
.cv .what>p:not(.org){margin:0;font-size:.86rem;line-height:1.65;color:var(--cv-text)}
.cv .skills{margin:9px 0 0;padding:0;list-style:none;display:flex;gap:7px;flex-wrap:wrap}
.cv .skills li{padding:3px 10px;font-size:.7rem;font-weight:700;background:#f6efe3;color:#8a5a12;border-radius:999px}
@media (max-width:560px){.cv>ol>li{grid-template-columns:1fr;gap:6px}.cv .when{text-align:left}.cv>ol>li::before,.cv>ol>li::after{display:none}.cv{padding:30px 26px}}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<section class="cv card" aria-labelledby="cv-title">
  <div class="card-body">
    <h2 class="card-title fw-bold mb-0" id="cv-title">Experience</h2>
    <p class="sub">A two-column CV timeline — dates left, story right.</p>
    <ol class="list-unstyled mb-0">
      <li>
        <p class="when text-end mb-0"><b class="d-block"><time datetime="2024">2024</time> — now</b>Berlin</p>
        <div class="what"><h3 class="fw-bold">Staff Product Designer</h3><p class="org">Meridian</p><p class="mb-0">Own the design system and the analytics surface used by 28k teams. Halved onboarding drop-off by redesigning the first-run flow.</p><ul class="skills list-unstyled mb-0 d-flex flex-wrap" aria-label="Skills"><li class="badge rounded-pill">Design systems</li><li class="badge rounded-pill">Prototyping</li><li class="badge rounded-pill">Research</li></ul></div>
      </li>
      <li>
        <p class="when text-end mb-0"><b class="d-block"><time datetime="2021">2021</time> — <time datetime="2024">2024</time></b>Remote</p>
        <div class="what"><h3 class="fw-bold">Senior Designer</h3><p class="org">Fieldnote</p><p class="mb-0">First design hire. Took the product from beta to 40k users and built the component library that outlived my tenure.</p><ul class="skills list-unstyled mb-0 d-flex flex-wrap" aria-label="Skills"><li class="badge rounded-pill">Product design</li><li class="badge rounded-pill">Frontend</li></ul></div>
      </li>
      <li>
        <p class="when text-end mb-0"><b class="d-block"><time datetime="2018">2018</time> — <time datetime="2021">2021</time></b>Porto</p>
        <div class="what"><h3 class="fw-bold">UI Designer</h3><p class="org">Studio Norte</p><p class="mb-0">Client work across fintech and culture — twelve shipped sites, two industry awards, one very patient art director.</p><ul class="skills list-unstyled mb-0 d-flex flex-wrap" aria-label="Skills"><li class="badge rounded-pill">Branding</li><li class="badge rounded-pill">Web design</li></ul></div>
      </li>
    </ol>
  </div>
</section>
CSS
/* Two-column CV timeline in a Bootstrap .card: dates left, role right, a rail and dot between them.
   Skills are .badge.rounded-pill list items. Under 560px the columns stack and the rail is dropped. */
.cv{--cv-accent:#b45309;--cv-line:#eae7df;--cv-muted:#706a5d;--cv-text:#5a544a;
  --bs-card-border-color:var(--cv-line);--bs-card-border-radius:16px;--bs-card-spacer-y:40px;--bs-card-spacer-x:44px;
  width:100%;max-width:640px;box-shadow:0 16px 38px -24px rgba(60,50,30,.25)}
.cv .card-title{font-size:1.25rem;letter-spacing:-.01em;line-height:normal}
.cv .sub{color:var(--cv-muted);font-size:.88rem;margin:4px 0 34px}
.cv .card-body>ol>li{display:grid;grid-template-columns:130px 1fr;gap:0 26px;position:relative;padding-bottom:32px}
.cv .card-body>ol>li:last-child{padding-bottom:0}
.cv .card-body>ol>li::before{content:"";position:absolute;left:146px;top:6px;bottom:-6px;width:2px;background:var(--cv-line)}
.cv .card-body>ol>li:last-child::before{bottom:auto;height:calc(100% - 6px)}
.cv .card-body>ol>li::after{content:"";position:absolute;left:141px;top:6px;width:12px;height:12px;border-radius:50%;background:var(--cv-accent);border:3px solid #fdf6ec}
.cv .when{font-size:.78rem;font-weight:700;color:var(--cv-muted);padding-top:2px;line-height:1.5}
.cv .when b{color:var(--cv-accent);font-size:.8rem;font-weight:700}
.cv .what{padding-left:16px}
.cv h3{margin:0 0 2px;font-size:1rem;line-height:normal}
.cv .org{margin-bottom:8px;font-size:.83rem;font-weight:600;color:var(--cv-muted)}
.cv .what>p:not(.org){font-size:.86rem;line-height:1.65;color:var(--cv-text)}
.cv .skills{margin-top:9px;gap:7px}
.cv .badge{--bs-badge-padding-x:10px;--bs-badge-padding-y:3px;--bs-badge-font-size:.7rem;--bs-badge-color:#8a5a12;line-height:normal;background:#f6efe3}
@media (max-width:560px){.cv{--bs-card-spacer-y:30px;--bs-card-spacer-x:26px}.cv .card-body>ol>li{grid-template-columns:1fr;gap:6px}.cv .when{text-align:left!important}.cv .card-body>ol>li::before,.cv .card-body>ol>li::after{display:none}}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<section aria-labelledby="cv-title" class="w-full max-w-[640px] rounded-2xl border border-[#eae7df] bg-white px-[26px] py-[30px] shadow-[0_16px_38px_-24px_rgba(60,50,30,.25)] min-[561px]:px-11 min-[561px]:py-10">
  <h2 id="cv-title" class="text-[1.25rem] font-bold tracking-[-.01em]">Experience</h2>
  <p class="mt-1 mb-[34px] text-[.88rem] text-[#706a5d]">A two-column CV timeline — dates left, story right.</p>
  <ol>
    <li class="relative grid grid-cols-1 gap-1.5 pb-8 min-[561px]:grid-cols-[130px_1fr] min-[561px]:gap-x-[26px] min-[561px]:gap-y-0 min-[561px]:before:absolute min-[561px]:before:top-1.5 min-[561px]:before:left-[146px] min-[561px]:before:w-0.5 min-[561px]:before:bg-[#eae7df] min-[561px]:before:-bottom-1.5 min-[561px]:after:absolute min-[561px]:after:top-1.5 min-[561px]:after:left-[141px] min-[561px]:after:size-3 min-[561px]:after:rounded-full min-[561px]:after:border-3 min-[561px]:after:border-[#fdf6ec] min-[561px]:after:bg-[#b45309]">
      <p class="pt-0.5 text-left text-[.78rem] leading-[1.5] font-bold text-[#706a5d] min-[561px]:text-right"><b class="block text-[.8rem] text-[#b45309]"><time datetime="2024">2024</time> — now</b>Berlin</p>
      <div class="pl-4"><h3 class="mb-0.5 text-[1rem] font-bold">Staff Product Designer</h3><p class="mb-2 text-[.83rem] font-semibold text-[#706a5d]">Meridian</p><p class="text-[.86rem] leading-[1.65] text-[#5a544a]">Own the design system and the analytics surface used by 28k teams. Halved onboarding drop-off by redesigning the first-run flow.</p><ul class="mt-[9px] flex flex-wrap gap-[7px]" aria-label="Skills"><li class="rounded-full bg-[#f6efe3] px-2.5 py-[3px] text-[.7rem] font-bold text-[#8a5a12]">Design systems</li><li class="rounded-full bg-[#f6efe3] px-2.5 py-[3px] text-[.7rem] font-bold text-[#8a5a12]">Prototyping</li><li class="rounded-full bg-[#f6efe3] px-2.5 py-[3px] text-[.7rem] font-bold text-[#8a5a12]">Research</li></ul></div>
    </li>
    <li class="relative grid grid-cols-1 gap-1.5 pb-8 min-[561px]:grid-cols-[130px_1fr] min-[561px]:gap-x-[26px] min-[561px]:gap-y-0 min-[561px]:before:absolute min-[561px]:before:top-1.5 min-[561px]:before:left-[146px] min-[561px]:before:w-0.5 min-[561px]:before:bg-[#eae7df] min-[561px]:before:-bottom-1.5 min-[561px]:after:absolute min-[561px]:after:top-1.5 min-[561px]:after:left-[141px] min-[561px]:after:size-3 min-[561px]:after:rounded-full min-[561px]:after:border-3 min-[561px]:after:border-[#fdf6ec] min-[561px]:after:bg-[#b45309]">
      <p class="pt-0.5 text-left text-[.78rem] leading-[1.5] font-bold text-[#706a5d] min-[561px]:text-right"><b class="block text-[.8rem] text-[#b45309]"><time datetime="2021">2021</time> — <time datetime="2024">2024</time></b>Remote</p>
      <div class="pl-4"><h3 class="mb-0.5 text-[1rem] font-bold">Senior Designer</h3><p class="mb-2 text-[.83rem] font-semibold text-[#706a5d]">Fieldnote</p><p class="text-[.86rem] leading-[1.65] text-[#5a544a]">First design hire. Took the product from beta to 40k users and built the component library that outlived my tenure.</p><ul class="mt-[9px] flex flex-wrap gap-[7px]" aria-label="Skills"><li class="rounded-full bg-[#f6efe3] px-2.5 py-[3px] text-[.7rem] font-bold text-[#8a5a12]">Product design</li><li class="rounded-full bg-[#f6efe3] px-2.5 py-[3px] text-[.7rem] font-bold text-[#8a5a12]">Frontend</li></ul></div>
    </li>
    <li class="relative grid grid-cols-1 gap-1.5 min-[561px]:grid-cols-[130px_1fr] min-[561px]:gap-x-[26px] min-[561px]:gap-y-0 min-[561px]:before:absolute min-[561px]:before:top-1.5 min-[561px]:before:left-[146px] min-[561px]:before:w-0.5 min-[561px]:before:bg-[#eae7df] min-[561px]:before:h-[calc(100%-6px)] min-[561px]:after:absolute min-[561px]:after:top-1.5 min-[561px]:after:left-[141px] min-[561px]:after:size-3 min-[561px]:after:rounded-full min-[561px]:after:border-3 min-[561px]:after:border-[#fdf6ec] min-[561px]:after:bg-[#b45309]">
      <p class="pt-0.5 text-left text-[.78rem] leading-[1.5] font-bold text-[#706a5d] min-[561px]:text-right"><b class="block text-[.8rem] text-[#b45309]"><time datetime="2018">2018</time> — <time datetime="2021">2021</time></b>Porto</p>
      <div class="pl-4"><h3 class="mb-0.5 text-[1rem] font-bold">UI Designer</h3><p class="mb-2 text-[.83rem] font-semibold text-[#706a5d]">Studio Norte</p><p class="text-[.86rem] leading-[1.65] text-[#5a544a]">Client work across fintech and culture — twelve shipped sites, two industry awards, one very patient art director.</p><ul class="mt-[9px] flex flex-wrap gap-[7px]" aria-label="Skills"><li class="rounded-full bg-[#f6efe3] px-2.5 py-[3px] text-[.7rem] font-bold text-[#8a5a12]">Branding</li><li class="rounded-full bg-[#f6efe3] px-2.5 py-[3px] text-[.7rem] font-bold text-[#8a5a12]">Web design</li></ul></div>
    </li>
  </ol>
</section>

About this set

A two-column experience timeline for a CV or portfolio. Dates and location sit right-aligned in a narrow left column, 2024 — now Berlin for example, and the role sits on the right with the job title, the company in muted bold, a short paragraph and a row of skill pills. A thin rail with an amber dot runs between the two columns and ties the jobs together. The card uses warm greys and an amber accent that print well and suit a personal site. Use it for work history, education, speaking history or any list of dated roles. The section is labelled by its Experience heading, jobs are an ordered list newest first with job titles as h3, start and end years are time elements, and each skill row is a small list labelled Skills. Each job is a CSS grid row of 130 pixels and the rest, and the rail and dot are pseudo-elements, so no empty spans are needed. Under 560 pixels the columns stack with the dates above the role and the rail is dropped. The Bootstrap version uses .card, .badge.rounded-pill and .text-end, and the Tailwind version uses a grid-cols-[130px_1fr] breakpoint.

What’s included

  • Dates column and role column on a CSS grid
  • Rail and amber dot drawn with pseudo-elements
  • Skill pills as a labelled list
  • Years in time elements, roles as h3 headings
  • Stacks under 560px with the rail removed

Accessibility

The card is a section named by its heading, jobs are an ordered list with an h3 per role, and each skills row is a list labelled Skills. Muted grey text was darkened to #706a5d so dates, companies and the intro reach 5.3:1. The rail and dot are decoration. There are no controls or motion.

Customise it

Change --cv-accent, --cv-line, --cv-muted and --cv-text on .cv, and the 130px column with the 146px and 141px rail positions together. Bootstrap pills take --bs-badge-color; in Tailwind edit the min-[561px]:grid-cols-[130px_1fr] and colour classes.