Skeleton
Blocks out an interface while it loads. Shapes take their size from what they stand in for, and screen readers hear one "Loading…" instead of every shape. Each example sits beside the real thing, so a difference in size shows at a glance.
Blocking out your own layout
skeleton yields s.text, s.circle, s.block and s.button to arrange with your own markup.
Ada Lovelace
Engineer · London
Wrote the first published algorithm for a machine, and saw it could reach beyond arithmetic.
Loading candidate
<div class="grid items-start gap-6 sm:grid-cols-2">
<%= card do %>
<div class="flex items-center gap-3">
<div class="size-12 shrink-0 rounded-full bg-indigo-200"></div>
<div class="min-w-0 flex-1">
<div class="font-semibold">Ada Lovelace</div>
<div>Engineer · London</div>
</div>
</div>
<p class="mt-3 mb-0">Wrote the first published algorithm for a machine, and saw it could reach beyond arithmetic.</p>
<% end %>
<%= card do %>
<%= skeleton label: "Loading candidate" do |s| %>
<div class="flex items-center gap-3">
<%= s.circle size: "3rem" %>
<div class="min-w-0 flex-1">
<div class="font-semibold"><%= s.text width: "60%" %></div>
<%= s.text width: "40%" %>
</div>
</div>
<p class="mt-3 mb-0"><%= s.text lines: 2 %></p>
<% end %>
<% end %>
</div>skeleton_badge, skeleton_icon and skeleton_item
A pill a badge's height, a row of chips, an icon button's square, and the item media object: a title over a smaller description, with an optional avatar.
Placed
RustGoSQL
Ada Lovelace
ada@example.com
Engineer
Analytical Engines
<div class="grid items-start gap-6 sm:grid-cols-2">
<div class="grid gap-3">
<div class="flex items-center gap-2">
<%= badge "Placed", tone: :good %>
<%= skeleton_badge %>
</div>
<div class="flex items-center gap-2">
<span class="flex gap-1"><%= badge "Rust", tone: :info %><%= badge "Go", tone: :info %><%= badge "SQL", tone: :info %></span>
<%= skeleton_badge count: 3 %>
</div>
</div>
<div class="flex flex-wrap items-center gap-2">
<%= button "More actions", :icon, icon: :pencil %>
<%= skeleton_icon %>
</div>
<div class="grid gap-4 text-sm">
<div class="flex items-center gap-3">
<%= avatar "Ada Lovelace", "aria-hidden": true %>
<div class="min-w-0">
<div class="font-medium">Ada Lovelace</div>
<div class="mt-0.5 text-xs text-neutral-500 dark:text-neutral-400">ada@example.com</div>
</div>
</div>
<%= skeleton_item avatar: :medium, width: "8rem" %>
</div>
<div class="grid gap-4 text-sm">
<div>
<div>Engineer</div>
<div class="mt-0.5 text-xs text-neutral-500 dark:text-neutral-400">Analytical Engines</div>
</div>
<%= skeleton_item width: "6rem" %>
</div>
</div>Deploy keys
Keys that can pull from this repository.
<div class="grid items-start gap-6 sm:grid-cols-2">
<%= page_header title: "Deploy keys", description: "Keys that can pull from this repository." do %>
<%= tag.button "Add key", type: "button", class: button_classes(:primary) %>
<% end %>
<%= page_header skeleton: true %>
</div>- Name
- Ada Lovelace
- Role
- Engineer
- Joined
- 10 December 1815
- Location
- London
Loading…
- Name
- Role
- Joined
- Location
<div class="grid items-start gap-6 sm:grid-cols-2">
<%= detail_list do |list|
list.item "Name", "Ada Lovelace"
list.item "Role", "Engineer"
list.item "Joined", "10 December 1815"
list.item "Location", "London"
end %>
<%= detail_list skeleton: true do |list|
list.item "Name"
list.item "Role"
list.item "Joined"
list.item "Location"
end %>
</div>Members
Ada, Grace and Katherine can see everything in this workspace, invite others, and manage its billing.
Members
<div class="grid items-start gap-6 sm:grid-cols-2">
<%= card title: "Members" do %>
Ada, Grace and Katherine can see everything in this workspace, invite others, and manage its billing.
<% end %>
<%= card title: "Members", skeleton: true %>
</div>