Open demo

CSS code

HTML
<div class="duo">
<div><span class="lbl">Business card</span>
<article class="bc" aria-labelledby="bc-maren" data-vcard>
  <div class="bc-grid">
    <div>
      <p class="bc-brand"><svg viewBox="0 0 32 32" width="28" height="28" aria-hidden="true" focusable="false"><path d="M16 3 29 27H3z" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linejoin="round"/><path d="M16 12l6.5 12h-13z" fill="currentColor"/></svg><span data-vc="org">Northlight Architects</span></p>
      <h3 class="bc-name" id="bc-maren" data-vc="fn">Maren Holt</h3>
      <p class="bc-title" data-vc="title">Principal architect</p>
    </div>
    <ul class="bc-rows">
      <li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="ic"><rect x="3" y="5" width="18" height="14" rx="2.5"/><path d="M3.5 6.5l8.5 6.5 8.5-6.5"/></svg><a href="mailto:[email protected]" data-vc="email">[email protected]</a>
        <button class="bc-copy" type="button" data-copy="[email protected]" data-what="Email address" aria-label="Copy email address"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="idle"><rect x="8.5" y="8.5" width="12" height="12" rx="2.5"/><path d="M15.5 8.5V6a2.5 2.5 0 0 0-2.5-2.5H6A2.5 2.5 0 0 0 3.5 6v7A2.5 2.5 0 0 0 6 15.5h2.5"/></svg><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="done"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg></button></li>
      <li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M5 3.5h3.2l1.6 4.2-2.1 1.4a11 11 0 0 0 7.2 7.2l1.4-2.1 4.2 1.6V19a1.9 1.9 0 0 1-2 1.9A16.5 16.5 0 0 1 3.1 5.5 1.9 1.9 0 0 1 5 3.5z"/></svg><a href="tel:+442079460321" data-vc="tel">+44 20 7946 0321</a>
        <button class="bc-copy" type="button" data-copy="+44 20 7946 0321" data-what="Phone number" aria-label="Copy phone number"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="idle"><rect x="8.5" y="8.5" width="12" height="12" rx="2.5"/><path d="M15.5 8.5V6a2.5 2.5 0 0 0-2.5-2.5H6A2.5 2.5 0 0 0 3.5 6v7A2.5 2.5 0 0 0 6 15.5h2.5"/></svg><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="done"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg></button></li>
      <li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3c2.5 2.6 3.8 5.6 3.8 9s-1.3 6.4-3.8 9c-2.5-2.6-3.8-5.6-3.8-9S9.5 5.6 12 3z"/></svg><a href="https://northlight.example" data-vc="url">northlight.example</a></li>
      <li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M12 21.5s7.5-6.4 7.5-12.2a7.5 7.5 0 0 0-15 0c0 5.8 7.5 12.2 7.5 12.2z"/><circle cx="12" cy="9.3" r="2.7"/></svg><span data-vc="adr">12 Wharf Road, London N1 7GR</span></li>
    </ul>
  </div>
  <div class="bc-foot">
    <a class="bc-save" href="data:text/vcard;charset=utf-8,BEGIN%3AVCARD%0D%0AVERSION%3A3.0%0D%0AN%3AHolt%3BMaren%3B%3B%3B%0D%0AFN%3AMaren%20Holt%0D%0AORG%3ANorthlight%20Architects%0D%0ATITLE%3APrincipal%20architect%0D%0AEMAIL%3BTYPE%3DINTERNET%2CWORK%3Amaren%40northlight.example%0D%0ATEL%3BTYPE%3DWORK%2CVOICE%3A%2B44%2020%207946%200321%0D%0AURL%3Ahttps%3A%2F%2Fnorthlight.example%0D%0AADR%3BTYPE%3DWORK%3A%3B%3B12%20Wharf%20Road%5C%2C%20London%20N1%207GR%3B%3B%3B%3B%0D%0AEND%3AVCARD%0D%0A" download="maren-holt.vcf"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M12 3.5v11.5M7 10.5l5 5 5-5M4.5 20.5h15"/></svg>Save contact (.vcf)<span class="sr-only"> for Maren Holt</span></a>
    <p class="bc-status" role="status"></p>
  </div>
</article></div>

<div><span class="lbl">Contact card with details</span>
<article class="bc bc-light" aria-labelledby="bc-diego" data-vcard>
  <div class="bc-head">
    <span class="bc-av" aria-hidden="true">DF</span>
    <div>
      <h3 class="bc-name" id="bc-diego" data-vc="fn">Diego Ferraz</h3>
      <p class="bc-title"><span data-vc="title">Account executive</span>, <span data-vc="org">Brightwell Logistics</span></p>
    </div>
  </div>
  <ul class="bc-rows">
    <li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><rect x="3" y="5" width="18" height="14" rx="2.5"/><path d="M3.5 6.5l8.5 6.5 8.5-6.5"/></svg><p><span class="bc-k">Email</span><a class="bc-v" href="mailto:[email protected]" data-vc="email">[email protected]</a></p>
      <button class="bc-copy" type="button" data-copy="[email protected]" data-what="Email address" aria-label="Copy email address"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="idle"><rect x="8.5" y="8.5" width="12" height="12" rx="2.5"/><path d="M15.5 8.5V6a2.5 2.5 0 0 0-2.5-2.5H6A2.5 2.5 0 0 0 3.5 6v7A2.5 2.5 0 0 0 6 15.5h2.5"/></svg><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="done"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg></button></li>
    <li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M5 3.5h3.2l1.6 4.2-2.1 1.4a11 11 0 0 0 7.2 7.2l1.4-2.1 4.2 1.6V19a1.9 1.9 0 0 1-2 1.9A16.5 16.5 0 0 1 3.1 5.5 1.9 1.9 0 0 1 5 3.5z"/></svg><p><span class="bc-k">Direct line</span><a class="bc-v" href="tel:+13125550147" data-vc="tel">+1 312 555 0147</a></p>
      <button class="bc-copy" type="button" data-copy="+1 312 555 0147" data-what="Phone number" aria-label="Copy phone number"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="idle"><rect x="8.5" y="8.5" width="12" height="12" rx="2.5"/><path d="M15.5 8.5V6a2.5 2.5 0 0 0-2.5-2.5H6A2.5 2.5 0 0 0 3.5 6v7A2.5 2.5 0 0 0 6 15.5h2.5"/></svg><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="done"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg></button></li>
    <li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M12 21.5s7.5-6.4 7.5-12.2a7.5 7.5 0 0 0-15 0c0 5.8 7.5 12.2 7.5 12.2z"/><circle cx="12" cy="9.3" r="2.7"/></svg><p><span class="bc-k">Office</span><span class="bc-v" data-vc="adr">400 W Lake St, Suite 1200, Chicago IL 60606</span></p></li>
    <li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3c2.5 2.6 3.8 5.6 3.8 9s-1.3 6.4-3.8 9c-2.5-2.6-3.8-5.6-3.8-9S9.5 5.6 12 3z"/></svg><p><span class="bc-k">Website</span><a class="bc-v" href="https://brightwell.example" data-vc="url">brightwell.example</a></p></li>
  </ul>
  <div class="bc-foot">
    <a class="bc-save" href="data:text/vcard;charset=utf-8,BEGIN%3AVCARD%0D%0AVERSION%3A3.0%0D%0AN%3AFerraz%3BDiego%3B%3B%3B%0D%0AFN%3ADiego%20Ferraz%0D%0AORG%3ABrightwell%20Logistics%0D%0ATITLE%3AAccount%20executive%0D%0AEMAIL%3BTYPE%3DINTERNET%2CWORK%3Adiego.ferraz%40brightwell.example%0D%0ATEL%3BTYPE%3DWORK%2CVOICE%3A%2B1%20312%20555%200147%0D%0AURL%3Ahttps%3A%2F%2Fbrightwell.example%0D%0AADR%3BTYPE%3DWORK%3A%3B%3B400%20W%20Lake%20St%5C%2C%20Suite%201200%5C%2C%20Chicago%20IL%2060606%3B%3B%3B%3B%0D%0AEND%3AVCARD%0D%0A" download="diego-ferraz.vcf"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M12 3.5v11.5M7 10.5l5 5 5-5M4.5 20.5h15"/></svg>Save contact (.vcf)<span class="sr-only"> for Diego Ferraz</span></a>
    <a class="bc-ghost" href="#">Book a call</a>
    <p class="bc-status" role="status"></p>
  </div>
</article></div>
</div>
CSS
/* Business and contact cards: each value is a real mailto:/tel: link with a copy button beside it, and "Save contact"
   downloads a .vcf built in the browser from the card's own fields (marked with data-vc). */
.bc{--bc-bg:#0f1f38;--bc-ink:#fff;--bc-muted:#b9c4d6;--bc-accent:#f2b134;--bc-line:rgba(255,255,255,.14);--bc-chip:rgba(255,255,255,.08);
  position:relative;overflow:hidden;padding:30px 30px 24px;border-radius:20px;background:var(--bc-bg);color:var(--bc-ink);
  box-shadow:0 30px 50px -30px rgba(15,31,56,.65)}
.bc::before{content:"";position:absolute;left:-150px;bottom:-200px;width:320px;height:320px;border-radius:50%;
  background:radial-gradient(circle,transparent 58%,rgba(242,177,52,.4) 59%,rgba(242,177,52,.4) 61%,transparent 62%),radial-gradient(circle,rgba(242,177,52,.18),transparent 60%);pointer-events:none}
.bc :where(h3,p,ul){margin:0;padding:0}
.bc-grid{position:relative;display:grid;grid-template-columns:1fr auto;gap:28px 32px}
.bc-brand{display:flex;align-items:center;gap:10px;font-size:.72rem;font-weight:700;letter-spacing:.2em;text-transform:uppercase;color:var(--bc-muted)}
.bc-brand svg{flex:none;color:var(--bc-accent)}
.bc-name{margin-top:34px;font-size:1.65rem;font-weight:800;letter-spacing:-.02em}
.bc-title{margin-top:4px;font-size:.95rem;font-weight:600;color:var(--bc-accent)}
.bc-rows{list-style:none;display:flex;flex-direction:column;gap:8px;align-self:end}
.bc-rows li{display:flex;align-items:center;gap:10px;min-height:30px;font-size:.92rem}
.bc-rows svg{flex:none}
.bc-rows li>svg{width:17px;height:17px;color:var(--bc-accent)}
.bc-rows a{color:inherit;text-decoration:none;border-radius:4px}
.bc-rows a:hover{text-decoration:underline;text-underline-offset:3px}
.bc-copy{display:grid;place-items:center;flex:none;width:30px;height:30px;margin-left:auto;padding:0;border:0;border-radius:8px;background:var(--bc-chip);color:var(--bc-muted);cursor:pointer;transition:background-color .2s,color .2s}
.bc-copy:hover{background:var(--bc-accent);color:var(--bc-bg)}
.bc-copy svg{width:15px;height:15px}
.bc-copy .done,.bc-copy.is-copied .idle{display:none}
.bc-copy.is-copied .done{display:block}
.bc-foot{position:relative;display:flex;flex-wrap:wrap;align-items:center;gap:10px 16px;margin-top:26px;padding-top:18px;border-top:1px solid var(--bc-line)}
.bc-save{display:inline-flex;align-items:center;gap:8px;padding:10px 16px;border-radius:10px;background:var(--bc-accent);color:var(--bc-bg);font-size:.88rem;font-weight:700;text-decoration:none;transition:background-color .2s}
.bc-save:hover{background:#ffc75a}
.bc-save svg{width:17px;height:17px}
.bc-status{font-size:.85rem;color:var(--bc-muted);min-height:1.2em}
.bc a:focus-visible,.bc-copy:focus-visible{outline:3px solid var(--bc-accent);outline-offset:2px}
@media (max-width:600px){.bc{padding:24px 22px 22px}.bc-grid{grid-template-columns:1fr}.bc-name{margin-top:24px}}
/* light contact card */
.bc-light{--bc-bg:#fff;--bc-ink:#14213d;--bc-muted:#4e5a6d;--bc-accent:#047857;--bc-line:#e3e7ee;--bc-chip:#eef2f6;box-shadow:0 1px 2px rgba(20,33,61,.06),0 24px 44px -30px rgba(20,33,61,.4)}
.bc-light::before{display:none}
.bc-head{display:flex;align-items:center;gap:14px}
.bc-av{display:grid;place-items:center;flex:none;width:60px;height:60px;border-radius:18px;background:linear-gradient(135deg,#047857,#0e7490);color:#fff;font-size:1.25rem;font-weight:800}
.bc-light .bc-name{margin-top:0;font-size:1.25rem}
.bc-light .bc-title{margin-top:2px;font-size:.9rem;font-weight:500;color:var(--bc-muted)}
.bc-light .bc-rows{margin-top:20px;gap:0}
.bc-light .bc-rows li{align-items:flex-start;gap:12px;padding:12px 0;border-top:1px solid var(--bc-line)}
.bc-light .bc-rows li>svg{margin-top:9px;color:var(--bc-accent)}
.bc-k{display:block;font-size:.72rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--bc-muted)}
.bc-v{display:block;margin-top:2px;font-size:.94rem;font-weight:600;overflow-wrap:anywhere}
.bc-light .bc-copy{margin-top:4px}
.bc-light .bc-copy:hover{color:#fff}
.bc-light .bc-foot{margin-top:6px}
.bc-light .bc-save{color:#fff}
.bc-light .bc-save:hover{background:#065f46}
.bc-ghost{display:inline-flex;align-items:center;padding:9px 15px;border:1.5px solid #8a96a8;border-radius:10px;color:var(--bc-ink);font-size:.88rem;font-weight:700;text-decoration:none}
.bc-ghost:hover{background:#f3f5f8}
.bc-light .bc-status{flex-basis:100%}
.bc .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
@media (prefers-reduced-motion:reduce){.bc-copy,.bc-save{transition:none}}
JavaScript
/* Copy buttons: copy data-copy to the clipboard, swap the icon to a tick for two seconds and announce it in the card's status line.
   Save contact: rebuild the .vcf link from the card's data-vc fields, so editing the visible text keeps the download in step.
   The link already holds the same vCard as a data: URL, so it downloads without JavaScript too. */
(function () {
  function copy(text) {
    if (navigator.clipboard && window.isSecureContext) return navigator.clipboard.writeText(text);
    return new Promise(function (resolve, reject) {
      var t = document.createElement('textarea'); t.value = text; t.setAttribute('readonly', ''); t.style.position = 'fixed'; t.style.opacity = '0';
      document.body.appendChild(t); t.select(); var ok = document.execCommand('copy'); t.remove(); ok ? resolve() : reject();
    });
  }
  document.querySelectorAll('[data-copy]').forEach(function (btn) {
    btn.addEventListener('click', function () {
      var status = btn.closest('[data-vcard]').querySelector('[role=status]');
      copy(btn.dataset.copy).then(function () {
        btn.classList.add('is-copied'); status.textContent = btn.dataset.what + ' copied';
        clearTimeout(btn._t); btn._t = setTimeout(function () { btn.classList.remove('is-copied'); status.textContent = ''; }, 2000);
      }, function () { status.textContent = 'Copy failed. Select the text and copy it instead.'; });
    });
  });
  var esc = function (v) { return v.replace(/\\/g, '\\\\').replace(/,/g, '\\,').replace(/;/g, '\\;'); };
  document.querySelectorAll('[data-vcard]').forEach(function (card) {
    var f = {}; card.querySelectorAll('[data-vc]').forEach(function (el) { f[el.dataset.vc] = el.textContent.trim(); });
    var link = card.querySelector('a[download]'); if (!link || !f.fn) return;
    var parts = f.fn.split(' '), family = parts.pop();
    var url = card.querySelector('[data-vc=url]');
    var lines = ['BEGIN:VCARD', 'VERSION:3.0', 'N:' + esc(family) + ';' + esc(parts.join(' ')) + ';;;', 'FN:' + esc(f.fn)];
    if (f.org) lines.push('ORG:' + esc(f.org));
    if (f.title) lines.push('TITLE:' + esc(f.title));
    if (f.email) lines.push('EMAIL;TYPE=INTERNET,WORK:' + f.email);
    if (f.tel) lines.push('TEL;TYPE=WORK,VOICE:' + f.tel);
    if (url) lines.push('URL:' + (url.getAttribute('href') || f.url));
    if (f.adr) lines.push('ADR;TYPE=WORK:;;' + esc(f.adr) + ';;;;');
    lines.push('END:VCARD');
    link.href = 'data:text/vcard;charset=utf-8,' + encodeURIComponent(lines.join('\r\n') + '\r\n');
  });
})();

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div class="duo">
<div><span class="lbl">Business card</span>
<article class="card bc" aria-labelledby="bc-maren" data-vcard>
  <div class="bc-grid">
    <div>
      <p class="bc-brand d-flex align-items-center"><svg viewBox="0 0 32 32" width="28" height="28" aria-hidden="true" focusable="false"><path d="M16 3 29 27H3z" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linejoin="round"/><path d="M16 12l6.5 12h-13z" fill="currentColor"/></svg><span data-vc="org">Northlight Architects</span></p>
      <h3 class="bc-name" id="bc-maren" data-vc="fn">Maren Holt</h3>
      <p class="bc-title" data-vc="title">Principal architect</p>
    </div>
    <ul class="bc-rows list-unstyled d-flex flex-column">
      <li class="d-flex align-items-center"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><rect x="3" y="5" width="18" height="14" rx="2.5"/><path d="M3.5 6.5l8.5 6.5 8.5-6.5"/></svg><a href="mailto:[email protected]" data-vc="email">[email protected]</a>
        <button class="btn bc-copy" type="button" data-copy="[email protected]" data-what="Email address" aria-label="Copy email address"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="idle"><rect x="8.5" y="8.5" width="12" height="12" rx="2.5"/><path d="M15.5 8.5V6a2.5 2.5 0 0 0-2.5-2.5H6A2.5 2.5 0 0 0 3.5 6v7A2.5 2.5 0 0 0 6 15.5h2.5"/></svg><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="done"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg></button></li>
      <li class="d-flex align-items-center"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M5 3.5h3.2l1.6 4.2-2.1 1.4a11 11 0 0 0 7.2 7.2l1.4-2.1 4.2 1.6V19a1.9 1.9 0 0 1-2 1.9A16.5 16.5 0 0 1 3.1 5.5 1.9 1.9 0 0 1 5 3.5z"/></svg><a href="tel:+442079460321" data-vc="tel">+44 20 7946 0321</a>
        <button class="btn bc-copy" type="button" data-copy="+44 20 7946 0321" data-what="Phone number" aria-label="Copy phone number"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="idle"><rect x="8.5" y="8.5" width="12" height="12" rx="2.5"/><path d="M15.5 8.5V6a2.5 2.5 0 0 0-2.5-2.5H6A2.5 2.5 0 0 0 3.5 6v7A2.5 2.5 0 0 0 6 15.5h2.5"/></svg><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="done"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg></button></li>
      <li class="d-flex align-items-center"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3c2.5 2.6 3.8 5.6 3.8 9s-1.3 6.4-3.8 9c-2.5-2.6-3.8-5.6-3.8-9S9.5 5.6 12 3z"/></svg><a href="https://northlight.example" data-vc="url">northlight.example</a></li>
      <li class="d-flex align-items-center"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M12 21.5s7.5-6.4 7.5-12.2a7.5 7.5 0 0 0-15 0c0 5.8 7.5 12.2 7.5 12.2z"/><circle cx="12" cy="9.3" r="2.7"/></svg><span data-vc="adr">12 Wharf Road, London N1 7GR</span></li>
    </ul>
  </div>
  <div class="bc-foot d-flex flex-wrap align-items-center">
    <a class="btn bc-save" href="data:text/vcard;charset=utf-8,BEGIN%3AVCARD%0D%0AVERSION%3A3.0%0D%0AN%3AHolt%3BMaren%3B%3B%3B%0D%0AFN%3AMaren%20Holt%0D%0AORG%3ANorthlight%20Architects%0D%0ATITLE%3APrincipal%20architect%0D%0AEMAIL%3BTYPE%3DINTERNET%2CWORK%3Amaren%40northlight.example%0D%0ATEL%3BTYPE%3DWORK%2CVOICE%3A%2B44%2020%207946%200321%0D%0AURL%3Ahttps%3A%2F%2Fnorthlight.example%0D%0AADR%3BTYPE%3DWORK%3A%3B%3B12%20Wharf%20Road%5C%2C%20London%20N1%207GR%3B%3B%3B%3B%0D%0AEND%3AVCARD%0D%0A" download="maren-holt.vcf"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M12 3.5v11.5M7 10.5l5 5 5-5M4.5 20.5h15"/></svg>Save contact (.vcf)<span class="visually-hidden"> for Maren Holt</span></a>
    <p class="bc-status" role="status"></p>
  </div>
</article></div>

<div><span class="lbl">Contact card with details</span>
<article class="card bc bc-light" aria-labelledby="bc-diego" data-vcard>
  <div class="bc-head d-flex align-items-center">
    <span class="bc-av" aria-hidden="true">DF</span>
    <div>
      <h3 class="bc-name" id="bc-diego" data-vc="fn">Diego Ferraz</h3>
      <p class="bc-title"><span data-vc="title">Account executive</span>, <span data-vc="org">Brightwell Logistics</span></p>
    </div>
  </div>
  <ul class="list-group list-group-flush">
    <li class="list-group-item d-flex align-items-start"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><rect x="3" y="5" width="18" height="14" rx="2.5"/><path d="M3.5 6.5l8.5 6.5 8.5-6.5"/></svg><p><span class="bc-k">Email</span><a class="bc-v" href="mailto:[email protected]" data-vc="email">[email protected]</a></p>
      <button class="btn bc-copy" type="button" data-copy="[email protected]" data-what="Email address" aria-label="Copy email address"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="idle"><rect x="8.5" y="8.5" width="12" height="12" rx="2.5"/><path d="M15.5 8.5V6a2.5 2.5 0 0 0-2.5-2.5H6A2.5 2.5 0 0 0 3.5 6v7A2.5 2.5 0 0 0 6 15.5h2.5"/></svg><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="done"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg></button></li>
    <li class="list-group-item d-flex align-items-start"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M5 3.5h3.2l1.6 4.2-2.1 1.4a11 11 0 0 0 7.2 7.2l1.4-2.1 4.2 1.6V19a1.9 1.9 0 0 1-2 1.9A16.5 16.5 0 0 1 3.1 5.5 1.9 1.9 0 0 1 5 3.5z"/></svg><p><span class="bc-k">Direct line</span><a class="bc-v" href="tel:+13125550147" data-vc="tel">+1 312 555 0147</a></p>
      <button class="btn bc-copy" type="button" data-copy="+1 312 555 0147" data-what="Phone number" aria-label="Copy phone number"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="idle"><rect x="8.5" y="8.5" width="12" height="12" rx="2.5"/><path d="M15.5 8.5V6a2.5 2.5 0 0 0-2.5-2.5H6A2.5 2.5 0 0 0 3.5 6v7A2.5 2.5 0 0 0 6 15.5h2.5"/></svg><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="done"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg></button></li>
    <li class="list-group-item d-flex align-items-start"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M12 21.5s7.5-6.4 7.5-12.2a7.5 7.5 0 0 0-15 0c0 5.8 7.5 12.2 7.5 12.2z"/><circle cx="12" cy="9.3" r="2.7"/></svg><p><span class="bc-k">Office</span><span class="bc-v" data-vc="adr">400 W Lake St, Suite 1200, Chicago IL 60606</span></p></li>
    <li class="list-group-item d-flex align-items-start"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3c2.5 2.6 3.8 5.6 3.8 9s-1.3 6.4-3.8 9c-2.5-2.6-3.8-5.6-3.8-9S9.5 5.6 12 3z"/></svg><p><span class="bc-k">Website</span><a class="bc-v" href="https://brightwell.example" data-vc="url">brightwell.example</a></p></li>
  </ul>
  <div class="bc-foot d-flex flex-wrap align-items-center">
    <a class="btn bc-save" href="data:text/vcard;charset=utf-8,BEGIN%3AVCARD%0D%0AVERSION%3A3.0%0D%0AN%3AFerraz%3BDiego%3B%3B%3B%0D%0AFN%3ADiego%20Ferraz%0D%0AORG%3ABrightwell%20Logistics%0D%0ATITLE%3AAccount%20executive%0D%0AEMAIL%3BTYPE%3DINTERNET%2CWORK%3Adiego.ferraz%40brightwell.example%0D%0ATEL%3BTYPE%3DWORK%2CVOICE%3A%2B1%20312%20555%200147%0D%0AURL%3Ahttps%3A%2F%2Fbrightwell.example%0D%0AADR%3BTYPE%3DWORK%3A%3B%3B400%20W%20Lake%20St%5C%2C%20Suite%201200%5C%2C%20Chicago%20IL%2060606%3B%3B%3B%3B%0D%0AEND%3AVCARD%0D%0A" download="diego-ferraz.vcf"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M12 3.5v11.5M7 10.5l5 5 5-5M4.5 20.5h15"/></svg>Save contact (.vcf)<span class="visually-hidden"> for Diego Ferraz</span></a>
    <a class="btn btn-outline-secondary" href="#">Book a call</a>
    <p class="bc-status" role="status"></p>
  </div>
</article></div>
</div>
CSS
/* Business and contact cards on Bootstrap .card, .list-group and .btn. Values are mailto:/tel: links with a copy button,
   and "Save contact" downloads a .vcf built in the browser from the card's data-vc fields. */
.bc{--bc-bg:#0f1f38;--bc-ink:#fff;--bc-muted:#b9c4d6;--bc-accent:#f2b134;--bc-line:rgba(255,255,255,.14);--bc-chip:rgba(255,255,255,.08);
  --bs-card-bg:var(--bc-bg);--bs-card-color:var(--bc-ink);--bs-card-border-width:0;--bs-card-border-radius:20px;
  overflow:hidden;padding:30px 30px 24px;color:var(--bc-ink);box-shadow:0 30px 50px -30px rgba(15,31,56,.65)}
.bc::before{content:"";position:absolute;left:-150px;bottom:-200px;width:320px;height:320px;border-radius:50%;
  background:radial-gradient(circle,transparent 58%,rgba(242,177,52,.4) 59%,rgba(242,177,52,.4) 61%,transparent 62%),radial-gradient(circle,rgba(242,177,52,.18),transparent 60%);pointer-events:none}
.bc :where(h3,p,ul){margin:0}
.bc-grid{position:relative;display:grid;grid-template-columns:1fr auto;gap:28px 32px}
.bc-brand{gap:10px;font-size:.72rem;font-weight:700;letter-spacing:.2em;text-transform:uppercase;color:var(--bc-muted)}
.bc-brand svg{flex:none;color:var(--bc-accent)}
.bc .bc-name{margin-top:34px;font-size:1.65rem;font-weight:800;letter-spacing:-.02em;line-height:normal}
.bc-title{margin-top:4px;font-size:.95rem;font-weight:600;color:var(--bc-accent)}
.bc-rows{gap:8px;align-self:end}
.bc-rows li{gap:10px;min-height:30px;font-size:.92rem}
.bc-rows svg{flex:none}
.bc-rows li>svg{width:17px;height:17px;color:var(--bc-accent)}
.bc-rows a{color:inherit;text-decoration:none;border-radius:4px}
.bc-rows a:hover{color:inherit;text-decoration:underline;text-underline-offset:3px}
.bc .bc-copy{--bs-btn-padding-x:0;--bs-btn-padding-y:0;--bs-btn-border-width:0;--bs-btn-border-radius:8px;--bs-btn-bg:var(--bc-chip);--bs-btn-color:var(--bc-muted);
  --bs-btn-hover-bg:var(--bc-accent);--bs-btn-hover-color:var(--bc-bg);--bs-btn-active-bg:var(--bc-accent);--bs-btn-active-color:var(--bc-bg);
  display:grid;place-items:center;flex:none;width:30px;height:30px;margin-left:auto;transition:background-color .2s,color .2s}
.bc-copy svg{width:15px;height:15px}
.bc-copy .done,.bc-copy.is-copied .idle{display:none}
.bc-copy.is-copied .done{display:block}
.bc-foot{position:relative;gap:10px 16px;margin-top:26px;padding-top:18px;border-top:1px solid var(--bc-line)}
.bc .bc-save{--bs-btn-padding-x:16px;--bs-btn-padding-y:10px;--bs-btn-font-size:.88rem;--bs-btn-font-weight:700;--bs-btn-line-height:normal;--bs-btn-border-width:0;--bs-btn-border-radius:10px;
  --bs-btn-bg:var(--bc-accent);--bs-btn-color:var(--bc-bg);--bs-btn-hover-bg:#ffc75a;--bs-btn-hover-color:var(--bc-bg);--bs-btn-active-bg:#ffc75a;--bs-btn-active-color:var(--bc-bg);
  display:inline-flex;align-items:center;gap:8px;transition:background-color .2s}
.bc-save svg{width:17px;height:17px}
.bc-status{font-size:.85rem;color:var(--bc-muted);min-height:1.2em}
.bc a:focus-visible,.bc .btn:focus-visible{outline:3px solid var(--bc-accent);outline-offset:2px;box-shadow:none}
@media (max-width:600px){.bc{padding:24px 22px 22px}.bc-grid{grid-template-columns:1fr}.bc .bc-name{margin-top:24px}}
/* light contact card */
.bc-light{--bc-bg:#fff;--bc-ink:#14213d;--bc-muted:#4e5a6d;--bc-accent:#047857;--bc-line:#e3e7ee;--bc-chip:#eef2f6;box-shadow:0 1px 2px rgba(20,33,61,.06),0 24px 44px -30px rgba(20,33,61,.4)}
.bc-light::before{display:none}
.bc-head{gap:14px}
.bc-av{display:grid;place-items:center;flex:none;width:60px;height:60px;border-radius:18px;background:linear-gradient(135deg,#047857,#0e7490);color:#fff;font-size:1.25rem;font-weight:800}
.bc-light .bc-name{margin-top:0;font-size:1.25rem}
.bc-light .bc-title{margin-top:2px;font-size:.9rem;font-weight:500;color:var(--bc-muted)}
.bc-light .list-group{--bs-list-group-bg:transparent;--bs-list-group-color:var(--bc-ink);--bs-list-group-border-color:var(--bc-line);--bs-list-group-item-padding-x:0;--bs-list-group-item-padding-y:12px;margin-top:20px;border-top:1px solid var(--bc-line)}
.bc-light .list-group-item{gap:12px}
.bc-light .list-group-item>svg{flex:none;width:17px;height:17px;margin-top:9px;color:var(--bc-accent)}
.bc-k{display:block;font-size:.72rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--bc-muted)}
.bc-v{display:block;margin-top:2px;font-size:.94rem;font-weight:600;overflow-wrap:anywhere}
.bc-light .list-group-item a{color:inherit;text-decoration:none;border-radius:4px}
.bc-light .list-group-item a:hover{text-decoration:underline;text-underline-offset:3px}
.bc-light .bc-copy{--bs-btn-hover-color:#fff;--bs-btn-active-color:#fff;margin-top:4px}
.bc-light .bc-foot{margin-top:6px}
.bc-light .bc-save{--bs-btn-color:#fff;--bs-btn-hover-bg:#065f46;--bs-btn-hover-color:#fff;--bs-btn-active-bg:#065f46;--bs-btn-active-color:#fff}
.bc .btn-outline-secondary{--bs-btn-padding-x:15px;--bs-btn-padding-y:9px;--bs-btn-font-size:.88rem;--bs-btn-font-weight:700;--bs-btn-line-height:normal;--bs-btn-border-width:1.5px;--bs-btn-border-radius:10px;
  --bs-btn-color:var(--bc-ink);--bs-btn-border-color:#8a96a8;--bs-btn-hover-color:var(--bc-ink);--bs-btn-hover-bg:#f3f5f8;--bs-btn-hover-border-color:#8a96a8;--bs-btn-active-color:var(--bc-ink);--bs-btn-active-bg:#e9edf2;--bs-btn-active-border-color:#8a96a8}
.bc-light .bc-status{flex-basis:100%}
@media (prefers-reduced-motion:reduce){.bc .btn{transition:none}}
JavaScript
/* Copy buttons: copy data-copy to the clipboard, swap the icon to a tick for two seconds and announce it in the card's status line.
   Save contact: rebuild the .vcf link from the card's data-vc fields, so editing the visible text keeps the download in step.
   The link already holds the same vCard as a data: URL, so it downloads without JavaScript too. */
(function () {
  function copy(text) {
    if (navigator.clipboard && window.isSecureContext) return navigator.clipboard.writeText(text);
    return new Promise(function (resolve, reject) {
      var t = document.createElement('textarea'); t.value = text; t.setAttribute('readonly', ''); t.style.position = 'fixed'; t.style.opacity = '0';
      document.body.appendChild(t); t.select(); var ok = document.execCommand('copy'); t.remove(); ok ? resolve() : reject();
    });
  }
  document.querySelectorAll('[data-copy]').forEach(function (btn) {
    btn.addEventListener('click', function () {
      var status = btn.closest('[data-vcard]').querySelector('[role=status]');
      copy(btn.dataset.copy).then(function () {
        btn.classList.add('is-copied'); status.textContent = btn.dataset.what + ' copied';
        clearTimeout(btn._t); btn._t = setTimeout(function () { btn.classList.remove('is-copied'); status.textContent = ''; }, 2000);
      }, function () { status.textContent = 'Copy failed. Select the text and copy it instead.'; });
    });
  });
  var esc = function (v) { return v.replace(/\\/g, '\\\\').replace(/,/g, '\\,').replace(/;/g, '\\;'); };
  document.querySelectorAll('[data-vcard]').forEach(function (card) {
    var f = {}; card.querySelectorAll('[data-vc]').forEach(function (el) { f[el.dataset.vc] = el.textContent.trim(); });
    var link = card.querySelector('a[download]'); if (!link || !f.fn) return;
    var parts = f.fn.split(' '), family = parts.pop();
    var url = card.querySelector('[data-vc=url]');
    var lines = ['BEGIN:VCARD', 'VERSION:3.0', 'N:' + esc(family) + ';' + esc(parts.join(' ')) + ';;;', 'FN:' + esc(f.fn)];
    if (f.org) lines.push('ORG:' + esc(f.org));
    if (f.title) lines.push('TITLE:' + esc(f.title));
    if (f.email) lines.push('EMAIL;TYPE=INTERNET,WORK:' + f.email);
    if (f.tel) lines.push('TEL;TYPE=WORK,VOICE:' + f.tel);
    if (url) lines.push('URL:' + (url.getAttribute('href') || f.url));
    if (f.adr) lines.push('ADR;TYPE=WORK:;;' + esc(f.adr) + ';;;;');
    lines.push('END:VCARD');
    link.href = 'data:text/vcard;charset=utf-8,' + encodeURIComponent(lines.join('\r\n') + '\r\n');
  });
})();

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div class="flex flex-wrap items-start gap-x-7 gap-y-14">
<div class="min-w-0 flex-[1_1_540px]"><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#4e5a6d] uppercase">Business card</span>
<article class="relative overflow-hidden rounded-[20px] bg-[#0f1f38] px-[30px] pt-[30px] pb-6 text-white shadow-[0_30px_50px_-30px_rgba(15,31,56,.65)] before:pointer-events-none before:absolute before:-bottom-[200px] before:-left-[150px] before:size-[320px] before:rounded-full before:bg-[radial-gradient(circle,transparent_58%,rgba(242,177,52,.4)_59%,rgba(242,177,52,.4)_61%,transparent_62%),radial-gradient(circle,rgba(242,177,52,.18),transparent_60%)] max-[600px]:px-[22px] max-[600px]:pt-6 max-[600px]:pb-[22px]" aria-labelledby="bc-maren" data-vcard>
  <div class="relative grid grid-cols-[1fr_auto] gap-x-8 gap-y-7 max-[600px]:grid-cols-1">
    <div>
      <p class="flex items-center gap-2.5 text-[.72rem] font-bold tracking-[.2em] text-[#b9c4d6] uppercase"><svg class="flex-none text-[#f2b134]" viewBox="0 0 32 32" width="28" height="28" aria-hidden="true" focusable="false"><path d="M16 3 29 27H3z" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linejoin="round"/><path d="M16 12l6.5 12h-13z" fill="currentColor"/></svg><span data-vc="org">Northlight Architects</span></p>
      <h3 class="mt-[34px] text-[1.65rem] font-extrabold tracking-[-.02em] max-[600px]:mt-6" id="bc-maren" data-vc="fn">Maren Holt</h3>
      <p class="mt-1 text-[.95rem] font-semibold text-[#f2b134]" data-vc="title">Principal architect</p>
    </div>
    <ul class="flex flex-col gap-2 self-end">
      <li class="flex min-h-[30px] items-center gap-2.5 text-[.92rem]"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="size-[17px] flex-none text-[#f2b134]"><rect x="3" y="5" width="18" height="14" rx="2.5"/><path d="M3.5 6.5l8.5 6.5 8.5-6.5"/></svg><a class="rounded text-inherit no-underline hover:underline hover:underline-offset-3 focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#f2b134]" href="mailto:[email protected]" data-vc="email">[email protected]</a>
        <button class="group ml-auto grid size-[30px] flex-none cursor-pointer place-items-center rounded-lg bg-white/8 text-[#b9c4d6] transition-[color,background-color,border-color] duration-200 hover:bg-[#f2b134] hover:text-[#0f1f38] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#f2b134] motion-reduce:transition-none" type="button" data-copy="[email protected]" data-what="Email address" aria-label="Copy email address"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="size-[15px] group-[.is-copied]:hidden"><rect x="8.5" y="8.5" width="12" height="12" rx="2.5"/><path d="M15.5 8.5V6a2.5 2.5 0 0 0-2.5-2.5H6A2.5 2.5 0 0 0 3.5 6v7A2.5 2.5 0 0 0 6 15.5h2.5"/></svg><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="hidden size-[15px] group-[.is-copied]:block"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg></button></li>
      <li class="flex min-h-[30px] items-center gap-2.5 text-[.92rem]"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="size-[17px] flex-none text-[#f2b134]"><path d="M5 3.5h3.2l1.6 4.2-2.1 1.4a11 11 0 0 0 7.2 7.2l1.4-2.1 4.2 1.6V19a1.9 1.9 0 0 1-2 1.9A16.5 16.5 0 0 1 3.1 5.5 1.9 1.9 0 0 1 5 3.5z"/></svg><a class="rounded text-inherit no-underline hover:underline hover:underline-offset-3 focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#f2b134]" href="tel:+442079460321" data-vc="tel">+44 20 7946 0321</a>
        <button class="group ml-auto grid size-[30px] flex-none cursor-pointer place-items-center rounded-lg bg-white/8 text-[#b9c4d6] transition-[color,background-color,border-color] duration-200 hover:bg-[#f2b134] hover:text-[#0f1f38] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#f2b134] motion-reduce:transition-none" type="button" data-copy="+44 20 7946 0321" data-what="Phone number" aria-label="Copy phone number"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="size-[15px] group-[.is-copied]:hidden"><rect x="8.5" y="8.5" width="12" height="12" rx="2.5"/><path d="M15.5 8.5V6a2.5 2.5 0 0 0-2.5-2.5H6A2.5 2.5 0 0 0 3.5 6v7A2.5 2.5 0 0 0 6 15.5h2.5"/></svg><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="hidden size-[15px] group-[.is-copied]:block"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg></button></li>
      <li class="flex min-h-[30px] items-center gap-2.5 text-[.92rem]"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="size-[17px] flex-none text-[#f2b134]"><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3c2.5 2.6 3.8 5.6 3.8 9s-1.3 6.4-3.8 9c-2.5-2.6-3.8-5.6-3.8-9S9.5 5.6 12 3z"/></svg><a class="rounded text-inherit no-underline hover:underline hover:underline-offset-3 focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#f2b134]" href="https://northlight.example" data-vc="url">northlight.example</a></li>
      <li class="flex min-h-[30px] items-center gap-2.5 text-[.92rem]"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="size-[17px] flex-none text-[#f2b134]"><path d="M12 21.5s7.5-6.4 7.5-12.2a7.5 7.5 0 0 0-15 0c0 5.8 7.5 12.2 7.5 12.2z"/><circle cx="12" cy="9.3" r="2.7"/></svg><span data-vc="adr">12 Wharf Road, London N1 7GR</span></li>
    </ul>
  </div>
  <div class="relative mt-[26px] flex flex-wrap items-center gap-x-4 gap-y-2.5 border-t border-white/14 pt-[18px]">
    <a class="inline-flex items-center gap-2 rounded-[10px] bg-[#f2b134] px-4 py-2.5 text-[.88rem] font-bold text-[#0f1f38] no-underline transition-[color,background-color,border-color] duration-200 hover:bg-[#ffc75a] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#f2b134] motion-reduce:transition-none" href="data:text/vcard;charset=utf-8,BEGIN%3AVCARD%0D%0AVERSION%3A3.0%0D%0AN%3AHolt%3BMaren%3B%3B%3B%0D%0AFN%3AMaren%20Holt%0D%0AORG%3ANorthlight%20Architects%0D%0ATITLE%3APrincipal%20architect%0D%0AEMAIL%3BTYPE%3DINTERNET%2CWORK%3Amaren%40northlight.example%0D%0ATEL%3BTYPE%3DWORK%2CVOICE%3A%2B44%2020%207946%200321%0D%0AURL%3Ahttps%3A%2F%2Fnorthlight.example%0D%0AADR%3BTYPE%3DWORK%3A%3B%3B12%20Wharf%20Road%5C%2C%20London%20N1%207GR%3B%3B%3B%3B%0D%0AEND%3AVCARD%0D%0A" download="maren-holt.vcf"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="size-[17px]"><path d="M12 3.5v11.5M7 10.5l5 5 5-5M4.5 20.5h15"/></svg>Save contact (.vcf)<span class="sr-only"> for Maren Holt</span></a>
    <p class="min-h-[1.2em] text-[.85rem] text-[#b9c4d6]" role="status"></p>
  </div>
</article></div>

<div class="min-w-0 flex-[1_1_320px]"><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#4e5a6d] uppercase">Contact card with details</span>
<article class="relative overflow-hidden rounded-[20px] bg-white px-[30px] pt-[30px] pb-6 text-[#14213d] shadow-[0_1px_2px_rgba(20,33,61,.06),0_24px_44px_-30px_rgba(20,33,61,.4)] max-[600px]:px-[22px] max-[600px]:pt-6 max-[600px]:pb-[22px]" aria-labelledby="bc-diego" data-vcard>
  <div class="flex items-center gap-3.5">
    <span class="grid size-[60px] flex-none place-items-center rounded-[18px] bg-[linear-gradient(135deg,#047857,#0e7490)] text-[1.25rem] font-extrabold text-white" aria-hidden="true">DF</span>
    <div>
      <h3 class="text-[1.25rem] font-extrabold tracking-[-.02em]" id="bc-diego" data-vc="fn">Diego Ferraz</h3>
      <p class="mt-0.5 text-[.9rem] text-[#4e5a6d]"><span data-vc="title">Account executive</span>, <span data-vc="org">Brightwell Logistics</span></p>
    </div>
  </div>
  <ul class="mt-5 divide-y divide-[#e3e7ee] border-t border-[#e3e7ee]">
    <li class="flex items-start gap-3 py-3"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="mt-[9px] size-[17px] flex-none text-[#047857]"><rect x="3" y="5" width="18" height="14" rx="2.5"/><path d="M3.5 6.5l8.5 6.5 8.5-6.5"/></svg><p><span class="block text-[.72rem] font-bold tracking-[.08em] text-[#4e5a6d] uppercase">Email</span><a class="mt-0.5 block rounded text-[.94rem] font-semibold wrap-anywhere text-inherit no-underline hover:underline hover:underline-offset-3 focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#047857]" href="mailto:[email protected]" data-vc="email">[email protected]</a></p>
      <button class="group mt-1 ml-auto grid size-[30px] flex-none cursor-pointer place-items-center rounded-lg bg-[#eef2f6] text-[#4e5a6d] transition-[color,background-color,border-color] duration-200 hover:bg-[#047857] hover:text-white focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#047857] motion-reduce:transition-none" type="button" data-copy="[email protected]" data-what="Email address" aria-label="Copy email address"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="size-[15px] group-[.is-copied]:hidden"><rect x="8.5" y="8.5" width="12" height="12" rx="2.5"/><path d="M15.5 8.5V6a2.5 2.5 0 0 0-2.5-2.5H6A2.5 2.5 0 0 0 3.5 6v7A2.5 2.5 0 0 0 6 15.5h2.5"/></svg><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="hidden size-[15px] group-[.is-copied]:block"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg></button></li>
    <li class="flex items-start gap-3 py-3"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="mt-[9px] size-[17px] flex-none text-[#047857]"><path d="M5 3.5h3.2l1.6 4.2-2.1 1.4a11 11 0 0 0 7.2 7.2l1.4-2.1 4.2 1.6V19a1.9 1.9 0 0 1-2 1.9A16.5 16.5 0 0 1 3.1 5.5 1.9 1.9 0 0 1 5 3.5z"/></svg><p><span class="block text-[.72rem] font-bold tracking-[.08em] text-[#4e5a6d] uppercase">Direct line</span><a class="mt-0.5 block rounded text-[.94rem] font-semibold wrap-anywhere text-inherit no-underline hover:underline hover:underline-offset-3 focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#047857]" href="tel:+13125550147" data-vc="tel">+1 312 555 0147</a></p>
      <button class="group mt-1 ml-auto grid size-[30px] flex-none cursor-pointer place-items-center rounded-lg bg-[#eef2f6] text-[#4e5a6d] transition-[color,background-color,border-color] duration-200 hover:bg-[#047857] hover:text-white focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#047857] motion-reduce:transition-none" type="button" data-copy="+1 312 555 0147" data-what="Phone number" aria-label="Copy phone number"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="size-[15px] group-[.is-copied]:hidden"><rect x="8.5" y="8.5" width="12" height="12" rx="2.5"/><path d="M15.5 8.5V6a2.5 2.5 0 0 0-2.5-2.5H6A2.5 2.5 0 0 0 3.5 6v7A2.5 2.5 0 0 0 6 15.5h2.5"/></svg><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="hidden size-[15px] group-[.is-copied]:block"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg></button></li>
    <li class="flex items-start gap-3 py-3"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="mt-[9px] size-[17px] flex-none text-[#047857]"><path d="M12 21.5s7.5-6.4 7.5-12.2a7.5 7.5 0 0 0-15 0c0 5.8 7.5 12.2 7.5 12.2z"/><circle cx="12" cy="9.3" r="2.7"/></svg><p><span class="block text-[.72rem] font-bold tracking-[.08em] text-[#4e5a6d] uppercase">Office</span><span class="mt-0.5 block text-[.94rem] font-semibold wrap-anywhere" data-vc="adr">400 W Lake St, Suite 1200, Chicago IL 60606</span></p></li>
    <li class="flex items-start gap-3 py-3"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="mt-[9px] size-[17px] flex-none text-[#047857]"><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3c2.5 2.6 3.8 5.6 3.8 9s-1.3 6.4-3.8 9c-2.5-2.6-3.8-5.6-3.8-9S9.5 5.6 12 3z"/></svg><p><span class="block text-[.72rem] font-bold tracking-[.08em] text-[#4e5a6d] uppercase">Website</span><a class="mt-0.5 block rounded text-[.94rem] font-semibold wrap-anywhere text-inherit no-underline hover:underline hover:underline-offset-3 focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#047857]" href="https://brightwell.example" data-vc="url">brightwell.example</a></p></li>
  </ul>
  <div class="relative mt-1.5 flex flex-wrap items-center gap-x-4 gap-y-2.5 border-t border-[#e3e7ee] pt-[18px]">
    <a class="inline-flex items-center gap-2 rounded-[10px] bg-[#047857] px-4 py-2.5 text-[.88rem] font-bold text-white no-underline transition-[color,background-color,border-color] duration-200 hover:bg-[#065f46] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#047857] motion-reduce:transition-none" href="data:text/vcard;charset=utf-8,BEGIN%3AVCARD%0D%0AVERSION%3A3.0%0D%0AN%3AFerraz%3BDiego%3B%3B%3B%0D%0AFN%3ADiego%20Ferraz%0D%0AORG%3ABrightwell%20Logistics%0D%0ATITLE%3AAccount%20executive%0D%0AEMAIL%3BTYPE%3DINTERNET%2CWORK%3Adiego.ferraz%40brightwell.example%0D%0ATEL%3BTYPE%3DWORK%2CVOICE%3A%2B1%20312%20555%200147%0D%0AURL%3Ahttps%3A%2F%2Fbrightwell.example%0D%0AADR%3BTYPE%3DWORK%3A%3B%3B400%20W%20Lake%20St%5C%2C%20Suite%201200%5C%2C%20Chicago%20IL%2060606%3B%3B%3B%3B%0D%0AEND%3AVCARD%0D%0A" download="diego-ferraz.vcf"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="size-[17px]"><path d="M12 3.5v11.5M7 10.5l5 5 5-5M4.5 20.5h15"/></svg>Save contact (.vcf)<span class="sr-only"> for Diego Ferraz</span></a>
    <a class="inline-flex items-center rounded-[10px] border-[1.5px] border-[#8a96a8] px-[15px] py-[9px] text-[.88rem] font-bold text-[#14213d] no-underline hover:bg-[#f3f5f8] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#047857]" href="#">Book a call</a>
    <p class="min-h-[1.2em] basis-full text-[.85rem] text-[#4e5a6d]" role="status"></p>
  </div>
</article></div>
</div>
JavaScript
/* Copy buttons: copy data-copy to the clipboard, swap the icon to a tick for two seconds and announce it in the card's status line.
   Save contact: rebuild the .vcf link from the card's data-vc fields, so editing the visible text keeps the download in step.
   The link already holds the same vCard as a data: URL, so it downloads without JavaScript too. */
(function () {
  function copy(text) {
    if (navigator.clipboard && window.isSecureContext) return navigator.clipboard.writeText(text);
    return new Promise(function (resolve, reject) {
      var t = document.createElement('textarea'); t.value = text; t.setAttribute('readonly', ''); t.style.position = 'fixed'; t.style.opacity = '0';
      document.body.appendChild(t); t.select(); var ok = document.execCommand('copy'); t.remove(); ok ? resolve() : reject();
    });
  }
  document.querySelectorAll('[data-copy]').forEach(function (btn) {
    btn.addEventListener('click', function () {
      var status = btn.closest('[data-vcard]').querySelector('[role=status]');
      copy(btn.dataset.copy).then(function () {
        btn.classList.add('is-copied'); status.textContent = btn.dataset.what + ' copied';
        clearTimeout(btn._t); btn._t = setTimeout(function () { btn.classList.remove('is-copied'); status.textContent = ''; }, 2000);
      }, function () { status.textContent = 'Copy failed. Select the text and copy it instead.'; });
    });
  });
  var esc = function (v) { return v.replace(/\\/g, '\\\\').replace(/,/g, '\\,').replace(/;/g, '\\;'); };
  document.querySelectorAll('[data-vcard]').forEach(function (card) {
    var f = {}; card.querySelectorAll('[data-vc]').forEach(function (el) { f[el.dataset.vc] = el.textContent.trim(); });
    var link = card.querySelector('a[download]'); if (!link || !f.fn) return;
    var parts = f.fn.split(' '), family = parts.pop();
    var url = card.querySelector('[data-vc=url]');
    var lines = ['BEGIN:VCARD', 'VERSION:3.0', 'N:' + esc(family) + ';' + esc(parts.join(' ')) + ';;;', 'FN:' + esc(f.fn)];
    if (f.org) lines.push('ORG:' + esc(f.org));
    if (f.title) lines.push('TITLE:' + esc(f.title));
    if (f.email) lines.push('EMAIL;TYPE=INTERNET,WORK:' + f.email);
    if (f.tel) lines.push('TEL;TYPE=WORK,VOICE:' + f.tel);
    if (url) lines.push('URL:' + (url.getAttribute('href') || f.url));
    if (f.adr) lines.push('ADR;TYPE=WORK:;;' + esc(f.adr) + ';;;;');
    lines.push('END:VCARD');
    link.href = 'data:text/vcard;charset=utf-8,' + encodeURIComponent(lines.join('\r\n') + '\r\n');
  });
})();

About this set

Digital business cards that people can act on. The business card is a navy card with a logo mark, the company name, a large name and title, and four contact rows for email, phone, website and address, ending in a Save contact (.vcf) button. The contact card with details is a light card with an initials avatar and labelled rows for email, direct line, office and website, plus Save contact and Book a call. Email and phone are real mailto: and tel: links, and each has a copy button that copies the value, swaps its icon for a tick for two seconds and writes Email address copied in a status line that screen readers announce. Save contact downloads a vCard 3.0 file. The link already holds the vCard as a data: URL, so it works without JavaScript, and the script rebuilds it from the visible fields marked data-vc, so editing the name or number on the card keeps the download in step. Copying uses the Clipboard API with a fallback for pages that are not served over HTTPS. Use them for team pages, event badges, link-in-bio pages and email footers on the web.

What’s included

  • Copy buttons for email and phone with a spoken confirmation
  • Save contact downloads a .vcf built in the browser
  • vCard works without JavaScript as a data: URL
  • Real mailto: and tel: links on every value
  • Dark business card and a light detailed contact card

Accessibility

Copy buttons are labelled Copy email address and Copy phone number, and each card has a role="status" line that announces what was copied. The Save contact link includes the person's name in hidden text. Links and buttons show a 3px focus outline, icons are hidden from screen readers, and colour transitions stop under prefers-reduced-motion.

Customise it

Set --bc-bg, --bc-ink, --bc-muted, --bc-accent and --bc-line on .bc (the light card overrides them in .bc-light). Edit the visible text and the data-copy values; the vCard follows the data-vc fields. In Tailwind change the colour utilities such as bg-[#0f1f38] and bg-[#f2b134].