About this snippet

Seven bars for the days of a week rise from the baseline one after another when the page loads. Hover a bar and its value appears above it, and the gridlines behind the bars give the eye something to read the heights against.

The data is a definition list. Each dt is a day label and each dd is a bar whose height comes from a custom property set inline as a percentage, so the numbers stay in the markup where a template can write them and the CSS does the drawing. The bars grow through a scaleY transform with transform-origin at the bottom, and a per-bar delay through another custom property produces the stagger. The value label is a pseudo-element reading the data attribute with attr, and the gridlines are a repeating gradient on the chart background rather than extra elements.

The list markup keeps every label paired with its bar, and the chart works without JavaScript.

Size
2.6 KB
Uses
HTML, CSS
Loads
Nothing external
Views
59
<section class="chart">
  <header>
    <h1>Orders this week</h1>
    <p>Hover a bar for the exact figure</p>
  </header>
  <dl class="bars">
    <dt>Mon</dt><dd style="--value: 62%; --i: 0;" data-value="312"></dd>
    <dt>Tue</dt><dd style="--value: 78%; --i: 1;" data-value="391"></dd>
    <dt>Wed</dt><dd style="--value: 54%; --i: 2;" data-value="270"></dd>
    <dt>Thu</dt><dd style="--value: 91%; --i: 3;" data-value="456"></dd>
    <dt>Fri</dt><dd style="--value: 100%; --i: 4;" data-value="502"></dd>
    <dt>Sat</dt><dd style="--value: 43%; --i: 5;" data-value="215"></dd>
    <dt>Sun</dt><dd style="--value: 36%; --i: 6;" data-value="180"></dd>
  </dl>
</section>
*, *::before, *::after {
  box-sizing: border-box;
}

body {
  font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  margin: 0;
  background: #f1f5f9;
  color: #0f172a;
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  padding: 20px;
}

.chart {
  width: 100%;
  max-width: 560px;
  background: #ffffff;
  padding: 28px 28px 24px;
  border-radius: 20px;
  box-shadow: 0 20px 40px -20px rgba(15, 23, 42, 0.25);
}

.chart header {
  margin-bottom: 40px;
}

.chart h1 {
  font-size: 1.25rem;
  margin: 0 0 4px;
}

.chart p {
  margin: 0;
  font-size: 0.875rem;
  color: #64748b;
}

.bars {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  grid-template-rows: 220px auto;
  grid-auto-flow: column;
  column-gap: 14px;
  row-gap: 10px;
  margin: 0;
  background-image: repeating-linear-gradient(to top, #e2e8f0 0 1px, transparent 1px 55px);
  background-size: 100% 220px;
  background-repeat: no-repeat;
}

.bars dt {
  grid-row: 2;
  text-align: center;
  font-size: 0.8125rem;
  color: #64748b;
}

.bars dd {
  grid-row: 1;
  align-self: end;
  position: relative;
  margin: 0;
  height: var(--value);
  border-radius: 8px 8px 3px 3px;
  background: linear-gradient(180deg, #60a5fa, #2563eb);
  transform-origin: bottom;
  animation: grow 0.8s cubic-bezier(0.2, 0.8, 0.2, 1) both;
  animation-delay: calc(var(--i) * 90ms);
  transition: filter 0.15s ease;
}

.bars dd:hover {
  filter: brightness(1.1);
}

.bars dd::after {
  content: attr(data-value);
  position: absolute;
  left: 50%;
  bottom: calc(100% + 8px);
  transform: translateX(-50%) translateY(4px);
  background: #0f172a;
  color: #ffffff;
  font-size: 0.75rem;
  font-weight: 600;
  padding: 4px 8px;
  border-radius: 6px;
  white-space: nowrap;
  opacity: 0;
  transition: opacity 0.15s ease, transform 0.15s ease;
  pointer-events: none;
}

.bars dd:hover::after {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

@keyframes grow {
  from { transform: scaleY(0); }
}
Esc
↑↓ moveEnter select

Start from a template

Open an .html file, or HTML, CSS, JS, Markdown, Less or TypeScript files. You can also drop them here. Styles and scripts go into their panes.

Share

Source

Keyboard shortcuts

Save