u/navid-jaberi

I made a Vue directive that turns your real component into its own skeleton loader (CSS only, nothing moves)
▲ 6 r/vuejs

I made a Vue directive that turns your real component into its own skeleton loader (CSS only, nothing moves)

I got tired of building a second, hand-made skeleton for every component and keeping it in sync, so I wrote `v-skeleton`:

<UserCard v-skeleton="loading" :user="user" />

While loading, every line of text becomes a bar, images and buttons become blocks, and borders and spacing stay. It never touches the DOM or any sizes, only a class and a few CSS variables, so nothing on the page shifts. It also waits 200ms before showing (no flash on fast requests) and works with SSR/Nuxt.

How it works, briefly: text is hidden with `-webkit-text-fill-color` (not `color`, which would also erase every currentColor border), and the bars are a `repeating-linear-gradient` mask sized with the `lh` unit, plus a border ring with `mask-composite` so table borders survive.

Live demo (Skeletonize page, tick "loading"): https://navidjaberi.github.io/vue-smart-loading-kit/
GitHub: https://github.com/navidjaberi/vue-smart-loading-kit

Known limits: the last line of a wrapped paragraph gets a full-width bar, and it needs browsers from late 2023 (:has, lh, mask-composite).

I'd really like feedback, especially layouts where it looks wrong. What do you use for skeletons today?

I wrote up how it works (and what testing it caught) here: https://dev.to/navidjaberi/i-built-a-vue-directive-that-turns-your-real-component-into-its-own-skeleton-3853

u/navid-jaberi — 12 days ago