SDK & Export API

Styling Guide

Last updated June 4, 2026

Styling Guide

The React and Vue components ship unstyled: there is no bundled CSS. You bring your own styles. This keeps the SDK tiny and lets the blog match your site exactly.

You have three levels of control:

  1. data-rankhiker attribute selectors on the default markup.
  2. Class props (className/cardClassName in React, class/cardClass in Vue).
  3. Full markup override via renderCard/render (React) or slots (Vue).

data-rankhiker hooks

Both adapters emit the same data-rankhiker attribute names on their default markup, so one stylesheet styles React and Vue identically.

SelectorElement
[data-rankhiker="blog-list"]Grid container in .
[data-rankhiker="blog-card"]Each card in the list.
[data-rankhiker="meta"]Author / reading-time / date row.
[data-rankhiker="blog-post"] wrapper.
[data-rankhiker="takeaways"]Key Takeaways aside.
[data-rankhiker="content"]Article body div (rendered HTML).
[data-rankhiker="faq"]FAQ section.
### Example stylesheet

A clean, responsive blog built purely on the hooks above:

css
/ List grid /
[data-rankhiker="blog-list"] {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1.5rem;
}

/ Cards / [data-rankhiker="blog-card"] { border: 1px solid #e5e7eb; border-radius: 12px; overflow: hidden; transition: box-shadow 0.2s; } [data-rankhiker="blog-card"]:hover { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08); } [data-rankhiker="blog-card"] img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; } [data-rankhiker="blog-card"] h2 { font-size: 1.125rem; margin: 0.75rem 1rem 0.25rem; } [data-rankhiker="blog-card"] p { margin: 0 1rem 1rem; color: #6b7280; }

/ Meta row / [data-rankhiker="meta"] { display: flex; gap: 0.75rem; font-size: 0.8125rem; color: #9ca3af; }

/ Single post / [data-rankhiker="blog-post"] { max-width: 720px; margin: 0 auto; }

/ Article prose / [data-rankhiker="content"] { line-height: 1.7; } [data-rankhiker="content"] h2 { margin-top: 2rem; } [data-rankhiker="content"] img { max-width: 100%; border-radius: 8px; }

/ Key takeaways / [data-rankhiker="takeaways"] { background: #f9fafb; border-left: 4px solid #8b5cf6; padding: 1rem 1.25rem; border-radius: 0 8px 8px 0; }

/ FAQ / [data-rankhiker="faq"] details { border-bottom: 1px solid #e5e7eb; padding: 0.75rem 0; } [data-rankhiker="faq"] summary { cursor: pointer; font-weight: 600; }

Class props

For utility frameworks like Tailwind, pass classes directly instead of writing global CSS.

React:

tsx
<BlogList className="grid gap-6 sm:grid-cols-2" cardClassName="rounded-xl border" />
<BlogPost slug={slug} className="prose mx-auto" />

Vue:

vue
<BlogList class="grid gap-6 sm:grid-cols-2" card-class="rounded-xl border" />
<BlogPost :slug="slug" class="prose mx-auto" />

Full markup override

When the default markup is not enough, replace it entirely.

React, via renderCard and render:

tsx
<BlogList
  renderCard={(post) => (
    <a key={post.id} href={/blog/${post.slug}} className="my-card">
      <h3>{post.title}</h3>
    </a>
  )}
/>

<BlogPost slug={slug} render={(post) => ( <article className="my-article"> <h1>{post.title}</h1> <div dangerouslySetInnerHTML={{ __html: post.content }} /> </article> )} />

Vue, via the card slot and the default slot:

vue
<BlogList>
  <template #card="{ post }">
    <a :href="/blog/${post.slug}" class="my-card">
      <h3>{{ post.title }}</h3>
    </a>
  </template>
</BlogList>

<BlogPost :slug="slug"> <template #default="{ post }"> <article class="my-article"> <h1>{{ post.title }}</h1> <div v-html="post.content" /> </article> </template> </BlogPost>

When you fully override markup, the data-rankhiker hooks are not emitted, so style those custom elements with your own classes.

Was this article helpful?