CSS Tutorial
CSS Icons
Icons can be SVG, emoji, or icon fonts. Size them with font-size or width so they stay sharp.
Prefer inline SVG
An icon is a small picture that stands for an action or a status: open, closed, kiln hot. The most reliable way to draw one on a Harbor studio page is an inline SVG — an<svg> element in the HTML. You size it with CSS width andheight. Vectors stay sharp when the visitor zooms.
Put the SVG next to the label it belongs to. Do not replace the word “Hours” with a clock unless the text is still there for people who do not share the metaphor.
Example
<style>
.hours {
color: #0c4a6e;
font-family: system-ui, sans-serif;
}
.hours svg {
width: 24px;
height: 24px;
vertical-align: middle;
margin-right: 8px;
color: teal;
}
</style>
<p class="hours">
<svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true">
<circle cx="12" cy="12" r="9" fill="none" stroke="currentColor" stroke-width="2"/>
<path d="M12 7v5l3 2" fill="none" stroke="currentColor" stroke-width="2"/>
</svg>
Harbor studio open 8–16
</p>Size the graphic in CSS (width: 24px) and keep matching width /height attributes so the layout does not jump before the stylesheet loads. Preview in/css/try and change 24 to 32.
Width keeps SVG sharp
Bitmap files (.png, .jpg) blur when you scale them up. SVG does not — it is math, not pixels. Set one size, usually width, and let height: auto follow the viewBox ratio, or set both to the same value for a square mark.
Example
<style>
.mark {
width: 32px;
height: 32px;
display: block;
color: teal;
}
.mark-lg {
width: 48px;
height: 48px;
color: #0284c7;
}
</style>
<svg class="mark" viewBox="0 0 24 24" aria-hidden="true">
<rect x="4" y="8" width="16" height="12" fill="currentColor" rx="2"/>
<path d="M8 8V6a4 4 0 0 1 8 0v2" fill="none" stroke="currentColor" stroke-width="2"/>
</svg>
<p style="color:#0c4a6e">Kiln lock, 32px.</p>
<svg class="mark mark-lg" viewBox="0 0 24 24" aria-hidden="true">
<rect x="4" y="8" width="16" height="12" fill="currentColor" rx="2"/>
<path d="M8 8V6a4 4 0 0 1 8 0v2" fill="none" stroke="currentColor" stroke-width="2"/>
</svg>
<p style="color:#0c4a6e">Same lock, 48px — still crisp.</p>currentColor and aria-hidden
Fill and stroke set to currentColor inherit the text color of the parent. A teal heading tints the icon; a white-on-teal button tints it white. You do not maintain a second color property for the graphic.
Decorative icons that sit beside visible text should use aria-hidden="true" so a screen reader does not announce a second “clock” after “open 8–16”. If the icon is the only label (an icon button), drop aria-hidden and give the control an accessible name witharia-label instead.
| Situation | Markup |
|---|---|
| Icon plus visible text | aria-hidden="true" on the SVG |
| Icon-only button | No aria-hidden; aria-label="Close" on the button |
| Meaningful standalone image | A short <title> inside the SVG |
Example
<style>
.btn {
padding: 8px 14px;
background: teal;
color: white;
border: 0;
font: 1rem/1.2 system-ui, sans-serif;
}
.btn svg {
width: 20px;
height: 20px;
vertical-align: middle;
margin-right: 8px;
}
</style>
<button class="btn" type="button">
<svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true">
<path fill="currentColor" d="M4 12h16M14 6l6 6-6 6"/>
</svg>
Book Harbor studio
</button>Emoji as a last resort
Emoji are font glyphs, not drawings you control. They change by operating system, they ignorefill, and they can read as informal on a booking form. If you must use one, treat it as decoration: wrap it, hide it from assistive tech, and keep the real words in the HTML. Size it withfont-size, the same knob that scales text.
Example
<style>
.fallback {
color: #0c4a6e;
font-family: system-ui, sans-serif;
}
.fallback .glyph {
font-size: 1.5rem;
line-height: 1;
vertical-align: middle;
margin-right: 8px;
}
</style>
<p class="fallback">
<span class="glyph" aria-hidden="true">⏰</span>
Harbor studio hours — emoji only when SVG is not available.
</p>Do not rely on emoji as the only meaning. A star character can render as a twinkle, a badge, or a missing-glyph box. Inline SVG with width is the default; emoji is the fallback.
Icon fonts
Icon fonts map a letter-like glyph to a picture. You size them with font-size, like emoji. They fail when the font file does not load (a random letter appears), they complicate translation, and they are easy to forget in aria-hidden. If a project already ships one, size it in rem and hide decorative glyphs. Prefer SVG for new Harbor studio UI.
| Kind | Size with | Sharp when zoomed |
|---|---|---|
| Inline SVG | width / height | Yes |
| Icon font | font-size | Yes, if the font loads |
| Emoji | font-size | Depends on the OS |
| PNG | width | No |
Next: display. Once icons and type sit in boxes, display decides whether those boxes stack or sit in a row.
Worked examples
The short listings above show one property. These sheets paint documents you would actually ship: a lab dashboard, a clinic form, a marks table, a nav bar.
CSS does not invent meaning. HTML already said what the pieces are. Cascade, specificity, and the box model decide how they look. The numbers are classroom values — current, pH, pulse, 3-4-5 — so the style has something real to sit on.
Preview them in the CSS editor at /css/try. Change one property and watch the page paint. The tags stay the same.
Biology
A pulse mark that is not the only signal
Emoji or SVG can sit in a span. Size with font-size or width. aria-hidden="true" if the nearby text already says “pulse”. Decorative icons should not be announced twice.
Example
<style>
.ico { font-size: 1.6rem; }
</style>
<p><span class="ico" aria-hidden="true">♥</span> 72 bpm</p>Engineering
A status glyph
If the icon is the only “ok”, give it a text alternative. Colour plus a heart is not enough for everyone.
Example
<style>
.ok { color: #16a34a; font-size: 1.4rem; }
</style>
<p><span class="ok" aria-hidden="true">●</span> logger ok</p>