Docs menu

Components · · 2 min read

Company-profile component: testimonial card & JS-free FAQ accordion

A FAQ accordion using the browser's built-in <details> element (still indexed by Google while collapsed) and a testimonial card with initial avatars + figure/blockquote semantics — code and preview side by side.

HTMLCSSCompany profileSEO
Live exampleRendered by the actual component — not an image.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<figure class="quote">
  <blockquote>
    Fit-out 800m² selesai 3 hari lebih cepat dari jadwal. Laporan progres
    masuk tiap Jumat tanpa diminta.
  </blockquote>
  <figcaption class="quote__by">
    <!-- Inisial: pengganti foto yang tidak pernah gagal dimuat -->
    <span class="avatar" aria-hidden="true">RS</span>
    <span>
      <b>Rina Susanti</b>
      <small>GM Operasional, PT Maju Bersama</small>
    </span>
  </figcaption>
</figure>

<!-- Accordion tanpa JavaScript: <details> sudah bisa buka-tutup sendiri -->
<div class="faq">
  <details open>
    <summary>Berapa lama pengerjaan fit-out kantor?<span class="faq__x">+</span></summary>
    <p>6–10 minggu untuk 500–1000m², tergantung kompleksitas MEP dan approval gedung.</p>
  </details>
  <details>
    <summary>Apakah termasuk perizinan gedung?<span class="faq__x">+</span></summary>
    <p>Ya. Pengurusan izin kerja dan koordinasi dengan building management masuk scope.</p>
  </details>
  <details>
    <summary>Bagaimana skema pembayarannya?<span class="faq__x">+</span></summary>
    <p>Termin: 40% mulai, 40% progres 50%, 20% serah terima setelah punch list beres.</p>
  </details>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
.quote {
  margin: 0 0 22px;
  border: 1px solid #e4e4e7;
  padding: 18px;
}
.quote blockquote {
  margin: 0;
  font-size: 14px;
  line-height: 1.65;
}
.quote__by {
  margin-top: 14px;
  display: flex;
  align-items: center;
  gap: 10px;
}
.avatar {
  width: 36px;
  height: 36px;
  flex: none;
  border-radius: 999px;
  background: #f0fdfa;
  color: #0f766e;
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 600;
}
.quote__by b { display: block; font-size: 13px; }
.quote__by small { display: block; font-size: 12px; color: #71717a; }

.faq { border-top: 1px solid #e4e4e7; }
.faq details { border-bottom: 1px solid #e4e4e7; }

.faq summary {
  list-style: none;         /* buang segitiga bawaan */
  cursor: pointer;
  padding: 13px 0;
  font-size: 14px;
  font-weight: 600;
  display: flex;
  justify-content: space-between;
  gap: 12px;
}
.faq summary::-webkit-details-marker { display: none; }

.faq__x {
  color: #0d9488;
  transition: transform 0.2s ease;
}
.faq details[open] .faq__x { transform: rotate(45deg); }

.faq p {
  margin: 0 0 14px;
  font-size: 13px;
  line-height: 1.7;
  color: #52525b;
}

Preview

These two components appear in almost every company profile I build — and both can be made without a single line of JavaScript. Open and close the FAQ in the preview panel: that’s pure HTML.

Accordions with <details>: a browser feature, not a library

Most tutorials teach accordions with a click listener plus class toggling. HTML already has the element:

<details open>
  <summary>How long does the work take?<span class="faq__x">+</span></summary>
  <p>6–10 weeks for 500–1000m²...</p>
</details>

What you get for free: open/close, keyboard navigation (Tab + Enter), an open state you can style, and — most important for a company profile — the content stays in the HTML, so Google’s crawler reads it even while collapsed. A JavaScript accordion that hides content with display:none is also indexed, but one that fetches its content on click is not.

Two lines of CSS remove the browser’s default triangle:

.faq summary { list-style: none; }
.faq summary::-webkit-details-marker { display: none; }

Then the + icon rotates 45° into a × when open, purely through the [open] selector:

.faq details[open] .faq__x { transform: rotate(45deg); }

One important note: if you add FAQPage JSON-LD (see the SEO & GEO build note), the <details> content must match the schema exactly — Google validates that the two agree.

Testimonials: initial avatars beat photos

Client photos are often unavailable, badly cropped, or fail to load. Initial avatars (RS, AN) always render perfectly, cost zero network requests, and never break:

.avatar {
  width: 36px; height: 36px;
  border-radius: 999px;
  display: grid; place-items: center;   /* two-line centering */
}

What actually drives credibility isn’t the photo but complete attribution: full name + role + company. Anonymous testimonials (“Mr. A, Jakarta”) actively lower trust — readers assume they’re invented.

Correct semantics

Note the elements: <figure> + <blockquote> + <figcaption>. This isn’t cosmetic — that combination tells machines (and screen-reader users) that the text is a quotation with a specific source. A plain <div class="quote"> communicates nothing.

Lessons

  • Before writing a listener, check whether HTML already has the element — <details>, <dialog>, and <datalist> are often a surprise.
  • Hidden content must still exist in the initial HTML if you care about SEO.
  • Testimonial credibility comes from complete attribution, not from a photo.

Want something like this built for your business?