your portal to the siena.codes web

HTML for Newbies

Every trick on the home page is plain HTML and CSS, with nothing to install or build. Each lesson below shows the effect, then the code that makes it. Copy anything you like.

1. View Source

This is how I learned. Right-click any page and pick View Page Source, or press Ctrl+U (⌘+Option+U on a Mac). You'll see the exact files this site sends you: index.html, style.css, and portal.js. There's a surprise near the top of the home page's source.

2. Beveled buttons

A bevel is just four border colors. Light on the top and left, dark on the bottom and right, so the button looks lit from the top left. Swap them while it's pressed and it sinks in.

.btn {
  background: linear-gradient(180deg, #ffffff, #d9dde6);
  border: 2px solid;
  border-color: #ffffff #8a91a3 #8a91a3 #ffffff;
}
.btn:active {
  border-color: #8a91a3 #ffffff #ffffff #8a91a3;
}

The four colors go top, right, bottom, left, clockwise from noon.

3. Title bars

Every box on the portal has a window-style title bar. It's a heading with a sideways gradient behind it and a tiny shadow under the white text.

My Cool Box

.bar {
  color: #fff;
  text-shadow: 1px 1px 0 rgba(0, 0, 0, .35);
  background: linear-gradient(90deg, #05506e, #0a86a8 70%, #22bfd8);
}

4. 88x31 buttons

The tiny badges are always 88 pixels wide and 31 tall. People traded them to link to each other's sites. These ones are drawn with CSS instead of images, so the patterns come from gradients.

quarterinch
.siena.codes
groover
.siena.codes
blinkie
.siena.codes

The checkerboard is one conic-gradient split into four quarters, tiled every 15 pixels. The white text-shadow makes the words readable over the pattern.

.b88 {
  display: block;
  width: 88px;
  height: 31px;
  font: 9px/11px Verdana, sans-serif;
  border: 1px solid #000;
}
.b-quilt {
  background:
    conic-gradient(#f8d98c 0 25%, #a8d4e6 0 50%,
                   #f8d98c 0 75%, #a8d4e6 0) 0 0 / 15px 15px;
  text-shadow: 0 0 3px #fff, 0 0 3px #fff;
}

Want a real image file instead? Make one at 88x31.siena.codes.

5. Starry background

The page background stacks three layers. Two are grids of tiny white dots made with radial-gradient, at different spacings so they don't line up. The third is the sky fade. background-attachment: fixed pins the stars in place while you scroll.

body {
  background-image:
    radial-gradient(circle at 25% 25%, rgba(255,255,255,.55) 0 1.5px, transparent 2px),
    radial-gradient(circle at 75% 70%, rgba(255,255,255,.4) 0 1px, transparent 1.5px),
    linear-gradient(180deg, #22bfd8, #d2f5fb);
  background-size: 28px 28px, 41px 41px, 100% 100%;
  background-attachment: fixed;
}

6. Chrome logo

The shiny logo is a gradient painted behind the text, then clipped to the letter shapes. The hard stop at 50% makes it look like metal. A thin outline sharpens the edges.

.logo a {
  background: linear-gradient(180deg,
    #0a86a8 0%, #d2f5fb 45%, #05506e 50%, #22bfd8 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-stroke: 1px #05506e;
}

7. Scrolling ticker

Old sites used the <marquee> tag. It still works in most browsers, but the HTML standard lists it as obsolete, so the What's New bar uses a CSS animation instead. The list slides left forever. A second copy of the list follows right behind it, so there's never a gap.

News
  • you are reading a tutorial
  • pause me by hovering
.ticker-items {
  display: flex;
  animation: scroll 38s linear infinite;
}
.ticker:hover .ticker-items {
  animation-play-state: paused;
}
@keyframes scroll {
  to { transform: translateX(-100%); }
}

9. Pixel art

Scale a small pixel image up and browsers blur it. image-rendering: pixelated stops the blur, so every pixel stays square. The webmaster doll is 32 by 125 pixels, shown at double size.

A 32 by 125 pixel doll of Siena at actual size The same doll at double size, still sharp
<img src="img/webmaster.png" width="64" height="250"
     style="image-rendering: pixelated" alt="...">

The sparkle and heart cursors are drawn from text. Each letter is one pixel color, and a dot means see-through. A script paints the grid onto a <canvas>, turns it into an image, and hands it to CSS cursor.

....o....
....o....
...oyo...
..oyyyo..
ooyywyyoo
..oyyyo..
...oyo...
....o....
....o....
The sparkle that grid draws
const colors = { o: "#05506e", y: "#fff0aa", w: "#ffffff" };
rows.forEach((row, y) =>
  [...row].forEach((ch, x) => {
    if (!colors[ch]) return;
    ctx.fillStyle = colors[ch];
    ctx.fillRect(x, y, 1, 1);
  })
);
document.documentElement.style.cursor =
  `url(${canvas.toDataURL()}) 4 4, auto`;

The two numbers after the image are the hotspot, the exact pixel that does the clicking.

10. Hit counter

Old hit counters were images served by someone else's computer, which counted every visitor. This one stores a number in your own browser with localStorage. It only counts your visits, and nobody else can see it.

let n = Number(localStorage.getItem("visits") || 0) + 1;
localStorage.setItem("visits", String(n));
counter.textContent = String(n).padStart(6, "0");

11. Be kind to visitors

Some people get dizzy from moving things, and their computer can say so. This turns the animations off for them.

@media (prefers-reduced-motion: reduce) {
  .spark, .new, .ticker-items { animation: none; }
}

Give every image an alt description for people using screen readers. Keep a visible outline on whatever has keyboard focus. Try pressing Tab on this page to see it.