Skip to content

Instantly share code, notes, and snippets.

@simonw

simonw/mini.md Secret

Created May 27, 2025 22:59
Show Gist options
  • Save simonw/cafd612b3982e3ad463788dd50287323 to your computer and use it in GitHub Desktop.
Save simonw/cafd612b3982e3ad463788dd50287323 to your computer and use it in GitHub Desktop.

2025-05-27T21:41:39 conversation: 01jw9v3x5vpy03k76crn3f8erm id: 01jw9v3a32r1s1cn6pa9ckeyae

Model: gpt-4.1-mini

Prompt

-- none --

Prompt fragments

b2203d90fe3d6fc3aaf227f37a3e535162f853eab1cc2d3cafc6b2b4ef3c6e12
@charset "UTF-8";
/*
pug index.pug -w
sass main.scss:main.css -w
*/
:root {
  color-scheme: dark;
  --cube-size: 5rem;
  --camera-distance: 50rem;
  --air-image: none;
  --pickaxe-image: url("./assets/pickaxe.png");
  --stone-image: url("./assets/stone.png");
  --grass-image: url("./assets/grass_side_carried.png");
  --grass-top-image: url("./assets/grass_carried.png");
  --dirt-image: url("./assets/dirt.png");
  --log-image: url("./assets/log_oak.png");
  --wood-image: url("./assets/oak_planks.png");
  --log-top-image: url("./assets/log_oak_top.png");
  --leaves-image: url("./assets/azalea_leaves.png");
  --glass-image: url("./assets/glass.png");
  pointer-events: none;
}

body {
  color: white;
  background-color: lightSkyBlue;
  block-size: 100vh;
  block-size: 100dvb;
  margin: 0;
  box-sizing: border-box;
  font-family: system-ui, sans-serif;
  overflow: hidden;
  display: grid;
  place-content: center center;
}

label, button {
  cursor: pointer;
}

h1, p {
  margin: 0;
}

h1, strong {
  font-weight: 600;
}

a {
  color: inherit;
}

.info {
  pointer-events: auto;
  z-index: 1;
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  padding: 0.75rem;
  margin-inline: auto;
  inline-size: fit-content;
  max-inline-size: min(60rem, 100vw - 10rem);
  background-color: rgba(17, 17, 17, 0.4666666667);
  --backdrop-filter: blur(.4rem);
  -webkit-backdrop-filter: var(--backdrop-filter);
  backdrop-filter: var(--backdrop-filter);
  border-radius: 0.6rem;
  border-start-start-radius: 0;
  border-start-end-radius: 0;
  text-align: center;
  box-shadow: 0 0 1.5rem rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: center;
  gap: 1rem;
}
.info strong {
  color: gold;
}
.info .text {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.info .close {
  padding-inline: 0.3rem;
}
.info .close::before {
  content: "⨉";
  font-size: 1.5rem;
}
.info .close > input[type=checkbox] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.info:has(.close > input[type=checkbox]:checked) {
  display: none;
}
.info .not-supported {
  border: 2px solid red;
  background-color: rgba(255, 0, 0, 0.2666666667);
  border-radius: 0.7rem;
  padding: 0.6rem 0.4rem;
}
@supports selector(:has(a)) {
  .info .not-supported {
    display: none;
  }
}

.controls {
  pointer-events: auto;
  z-index: 2;
  position: absolute;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 1.25rem;
  border-radius: 0.8rem;
  box-shadow: 0 0 1.5rem rgba(0, 0, 0, 0.4);
  background-color: rgba(34, 34, 34, 0.5333333333);
  --backdrop-filter: blur(.3rem);
  -webkit-backdrop-filter: var(--backdrop-filter);
  backdrop-filter: var(--backdrop-filter);
  padding: 0.75rem;
  padding-block-start: 0.5rem;
  margin-block-end: 0.75rem;
  inset-block-end: 0;
  inset-inline: 0;
  margin-inline: auto;
  inline-size: fit-content;
  max-inline-size: calc(100vw - 4rem);
}
.controls .block-chooser {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.controls .block-chooser > label {
  display: block;
  inline-size: 3rem;
  block-size: 3rem;
  border-radius: 0.3rem;
  box-sizing: border-box;
  background-size: 100% 100%;
  background-repeat: no-repeat;
  image-rendering: pixelated;
  outline-offset: 1px;
}
.controls .block-chooser > label.air {
  background-image: var(--air-image);
}
.controls .block-chooser > label.stone {
  background-image: var(--stone-image);
}
.controls .block-chooser > label.grass {
  background-image: var(--grass-image);
}
.controls .block-chooser > label.dirt {
  background-image: var(--dirt-image);
}
.controls .block-chooser > label.log {
  background-image: var(--log-image);
}
.controls .block-chooser > label.wood {
  background-image: var(--wood-image);
}
.controls .block-chooser > label.leaves {
  background-image: var(--leaves-image);
}
.controls .block-chooser > label.glass {
  background-image: var(--glass-image);
}
.controls .block-chooser > label.air {
  background-image: var(--pickaxe-image);
}
.controls .block-chooser > label:hover {
  outline: 2px solid silver;
}
.controls .block-chooser > label:has(> input[type=radio]:checked) {
  outline: 2px solid white;
}
.controls .block-chooser > label > input[type=radio] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.controls:has(> .block-chooser > .air > input[type=radio]:checked) ~ main .cubes-container > .cube:not(.air) {
  display: none;
}
.controls:has(> .block-chooser > .stone > input[type=radio]:checked) ~ main .cubes-container > .cube:not(.stone) {
  display: none;
}
.controls:has(> .block-chooser > .grass > input[type=radio]:checked) ~ main .cubes-container > .cube:not(.grass) {
  display: none;
}
.controls:has(> .block-chooser > .dirt > input[type=radio]:checked) ~ main .cubes-container > .cube:not(.dirt) {
  display: none;
}
.controls:has(> .block-chooser > .log > input[type=radio]:checked) ~ main .cubes-container > .cube:not(.log) {
  display: none;
}
.controls:has(> .block-chooser > .wood > input[type=radio]:checked) ~ main .cubes-container > .cube:not(.wood) {
  display: none;
}
.controls:has(> .block-chooser > .leaves > input[type=radio]:checked) ~ main .cubes-container > .cube:not(.leaves) {
  display: none;
}
.controls:has(> .block-chooser > .glass > input[type=radio]:checked) ~ main .cubes-container > .cube:not(.glass) {
  display: none;
}
.controls .block-chooser, .controls .move-button-pair {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(auto, 1fr));
  justify-items: center;
  gap: 0.5rem;
}
.controls .block-chooser > *:not(.label), .controls .move-button-pair > *:not(.label) {
  grid-row: 2;
}
.controls .block-chooser > .label, .controls .move-button-pair > .label {
  grid-column: 1/span 2;
}
.controls .block-chooser > .label {
  grid-column-end: span 8;
}
.controls .move-buttons {
  display: flex;
  align-items: center;
  gap: 1.25rem;
}
.controls .move-buttons button {
  display: grid;
  place-content: center;
  inline-size: 3rem;
  block-size: 3rem;
  border: none;
  border-radius: 0.3rem;
  background-color: rgba(0, 0, 0, 0.2);
  font-size: 1.5rem;
}
.controls .move-buttons button:hover {
  background-color: rgba(0, 0, 0, 0.3333333333);
}
.controls .move-buttons button:active {
  background-color: rgba(0, 0, 0, 0.4666666667);
}
.controls:has(.up:active) ~ main .down {
  animation-play-state: running;
}
.controls:has(.down:active) ~ main .up {
  animation-play-state: running;
}
.controls:has(.clockwise:active) ~ main .clockwise {
  animation-play-state: running;
}
.controls:has(.counterclockwise:active) ~ main .counterclockwise {
  animation-play-state: running;
}
.controls:has(.forwards:active) ~ main .backwards {
  animation-play-state: running;
}
.controls:has(.backwards:active) ~ main .forwards {
  animation-play-state: running;
}
.controls:has(.look-up:active) ~ main .look-up {
  animation-play-state: running;
}
.controls:has(.look-down:active) ~ main .look-down {
  animation-play-state: running;
}

main {
  perspective: var(--camera-distance);
  perspective-origin: center center;
}
main, main * {
  transform-style: preserve-3d;
}

.content {
  rotate: x -50grad;
  --animation-duration: 10000s;
  --max-translation: 400000rem;
  --max-rotation: 3000turn;
}
.content .initial-camera-position {
  translate: 0 calc(var(--layers) * var(--cube-size) * 0.4) calc(var(--camera-distance) - var(--rows) * var(--cube-size) * 0.9);
}
.content, .content .look-up, .content .look-down {
  transform-origin: 0 0 var(--camera-distance);
}
.content .look-up {
  animation: var(--animation-duration) linear 1ms paused look-up;
}
@keyframes look-up {
  from {
    rotate: x 0turn;
  }
  to {
    rotate: x calc(var(--max-rotation));
  }
}
.content .look-down {
  animation: var(--animation-duration) linear 1ms paused look-down;
}
@keyframes look-down {
  from {
    rotate: x 0turn;
  }
  to {
    rotate: x calc(-1 * var(--max-rotation));
  }
}
.content .down {
  animation: var(--animation-duration) linear 1ms paused move-down;
}
@keyframes move-down {
  from {
    translate: 0 0;
  }
  to {
    translate: 0 calc(var(--max-translation));
  }
}
.content .up {
  animation: var(--animation-duration) linear 1ms paused move-up;
}
@keyframes move-up {
  from {
    translate: 0 0;
  }
  to {
    translate: 0 calc(-1 * var(--max-translation));
  }
}
.content .forwards {
  animation: var(--animation-duration) linear 1ms paused move-forwards;
}
@keyframes move-forwards {
  from {
    translate: 0 0 0;
  }
  to {
    translate: 0 0 calc(-1 * var(--max-translation));
  }
}
.content .backwards {
  animation: var(--animation-duration) linear 1ms paused move-backwards;
}
@keyframes move-backwards {
  from {
    translate: 0 0 0;
  }
  to {
    translate: 0 0 calc(var(--max-translation));
  }
}
.content .clockwise {
  animation: var(--animation-duration) linear 1ms paused rotate-clockwise;
}
@keyframes rotate-clockwise {
  from {
    rotate: y 0turn;
  }
  to {
    rotate: y calc(-1 * var(--max-rotation));
  }
}
.content .counterclockwise {
  animation: var(--animation-duration) linear 1ms paused rotate-counterclockwise;
}
@keyframes rotate-counterclockwise {
  from {
    rotate: y 0turn;
  }
  to {
    rotate: y calc(var(--max-rotation));
  }
}
.content .blocks {
  position: relative;
  translate: calc(-0.5 * var(--columns) * var(--cube-size)) calc(-0.5 * var(--layers) * var(--cube-size)) calc(-0.5 * var(--rows) * var(--cube-size));
}
.content .blocks .cubes-container {
  pointer-events: auto;
  translate: calc(var(--column) * var(--cube-size)) calc(var(--layer) * var(--cube-size)) calc(var(--row) * var(--cube-size));
}
.content .blocks .cubes-container:has(> .cube.air > input[type=radio]:checked) {
  display: none;
}
.content .blocks .cubes-container:has(> .cube.air > input[type=radio]:checked) {
  --background-image: var(--air-image);
}
.content .blocks .cubes-container:has(> .cube.stone > input[type=radio]:checked) {
  --background-image: var(--stone-image);
}
.content .blocks .cubes-container:has(> .cube.grass > input[type=radio]:checked) {
  --background-image: var(--grass-image);
}
.content .blocks .cubes-container:has(> .cube.dirt > input[type=radio]:checked) {
  --background-image: var(--dirt-image);
}
.content .blocks .cubes-container:has(> .cube.log > input[type=radio]:checked) {
  --background-image: var(--log-image);
}
.content .blocks .cubes-container:has(> .cube.wood > input[type=radio]:checked) {
  --background-image: var(--wood-image);
}
.content .blocks .cubes-container:has(> .cube.leaves > input[type=radio]:checked) {
  --background-image: var(--leaves-image);
}
.content .blocks .cubes-container:has(> .cube.glass > input[type=radio]:checked) {
  --background-image: var(--glass-image);
}
.content .blocks .cubes-container .cube {
  position: absolute;
  block-size: var(--cube-size);
  inline-size: var(--cube-size);
}
.content .blocks .cubes-container .cube > input[type=radio] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.content .blocks .cubes-container .cube > label {
  position: absolute;
  inset: 0;
  background-image: var(--background-image);
  image-rendering: pixelated;
  background-size: 100% 100%;
  transform-origin: center center calc(-1 * var(--cube-size) / 2);
  translate: 0 0 calc(var(--cube-size) / 2);
  box-sizing: border-box;
}
.content .blocks .cubes-container .cube > label.front {
  rotate: y 0grad;
  filter: brightness(92%);
}
.content .blocks .cubes-container .cube > label.back {
  rotate: y 200grad;
  filter: brightness(68%);
}
.content .blocks .cubes-container .cube > label.left {
  rotate: y 100grad;
  filter: brightness(76%);
}
.content .blocks .cubes-container .cube > label.right {
  rotate: y -100grad;
  filter: brightness(84%);
}
.content .blocks .cubes-container .cube > label.top {
  rotate: x 100grad;
  filter: brightness(100%);
}
.content .blocks .cubes-container .cube > label.bottom {
  rotate: x -100grad;
  filter: brightness(60%);
}
.content .blocks .cubes-container:has(> .cube.grass > input[type=radio]:checked) > .cube > label.top {
  background-image: var(--grass-top-image);
}
.content .blocks .cubes-container:has(> .cube.grass > input[type=radio]:checked) > .cube > label.bottom {
  background-image: var(--dirt-image);
}
.content .blocks .cubes-container:has(> .cube.log > input[type=radio]:checked) > .cube > label:is(.top, bottom) {
  background-image: var(--log-top-image);
}

.cubes-container > .cube > label:hover,
.controls:has(.air > input[type=radio]:checked) ~ main .cubes-container:hover > .cube > label {
  --outline-width: calc(var(--cube-size) / 24);
  outline: var(--outline-width) solid white;
  outline-offset: calc(-1 * var(--outline-width));
}

.controls:has(.air > input[type=radio]:checked) ~ main .cubes-container:hover > .cube > label {
  filter: brightness(70%);
}

/*# sourceMappingURL=main.css.map */

System

explain all the tricks used by this CSS

Response

This CSS implements a complex, interactive 3D block-building interface, inspired by voxel games like Minecraft. Let me break down and explain the various clever and advanced tricks it uses:


1. CSS Variables for Theming and Sizes

  • :root defines many custom properties (CSS variables) like:
    • --cube-size: size of each block cube (5rem).
    • --camera-distance: used for 3D perspective depth.
    • Various --{block}-image holding URLs for Minecraft-style textures (stone, grass, dirt, etc).
  • These variables allow easy styling updates and consistent reuse, and tune 3D settings.

2. Dark Mode Support via color-scheme

  • color-scheme: dark on :root enables automatic form control styling for dark mode.

3. Pointer Events Control for Usability

  • The entire app disables pointer events by default on :root (no interaction).
  • Specific interactive elements like .info, .controls, and .cubes-container enable pointer-events for user interaction.

4. Layout with Modern CSS

  • Uses display: grid; place-content: center; in body to perfectly center the content.
  • block-size: 100vh; block-size: 100dvb; two size units ensuring it fills viewport height robustly (viewport height and dynamic viewport block units).

5. Backdrop Filters With Fallbacks

  • .info and .controls use backdrop-filter with:
    • A CSS variable declaration --backdrop-filter: blur(...) cached in a variable.
    • Applied with standard and vendor-prefixed versions.
  • Provides a blurred translucent background behind content overlays for nice UI.

6. Using :has() for Powerful State-based Styling

  • This advanced CSS pseudo-class lets styles be applied based on child state.
  • Examples:
    • .info:has(.close > input[type=checkbox]:checked) hides the info panel when checkbox inside .close is checked (custom close button).
    • .controls:has(> .block-chooser > .stone > input[type=radio]:checked) ~ main .cubes-container > .cube:not(.stone) hides blocks that don't match the selected type.
    • Highlight currently selected block with outline by styling label with :has(> input[type=radio]:checked).
    • Animations triggered when buttons inside .controls are active using :has(:active) selector.

This use of :has() eliminates the need for JavaScript for many state-driven UI behaviors.


7. Animations Used for Camera/Content Movement

  • Defines several keyframe animations like move-up, rotate-clockwise, look-up, etc.
  • These animations have duration set to a very large value (10000s) and are initially paused.
  • When control buttons are pressed (:has(.up:active)), the related animation playback state is toggled to running.
  • This lets CSS animate camera or block group translations and rotations smoothly without JS.

8. Robust 3D Transformations

  • main has a perspective to simulate 3D scene.
  • Children have transform-style: preserve-3d to keep 3D layering.
  • .content has rotated X by -50 grads (a metric angle unit similar to degrees).
  • Cubes and blocks positioned in 3D space using CSS variables and 3D translate transforms calculated from --row, --column, --layer multiplied with --cube-size.
  • Each cube side (front, back, left, right, top, bottom) rotated in 3D space to form a cube using rotate transforms.
  • Filters (brightness()) applied to different faces simulates directional lighting—top face brightest, bottom darkest.

9. CSS-only Radio Controls for Block Interaction

  • Blocks and block chooser items use hidden radio inputs wrapped inside labels.
  • Clicking a label selects a block type or activates some interaction.
  • CSS :checked states on inputs are used heavily with sibling general or descendant selectors to toggle UI state.
  • Example: selecting a block type filter hides all cubes except the selected type.

10. Image Reuse and Background Textures

  • Block faces use background-image pulled from CSS variables defined in :root.
  • image-rendering: pixelated; ensures block textures remain crisp and low-res styled.
  • Different images are applied for different cubes and faces (grass top vs sides, log top vs sides etc).

11. Accessible Close Button with Emoji & Hidden Checkbox

  • Close button .close uses a pseudo-element ::before to show the × emoji.
  • The real toggle is a hidden checkbox input.
  • Clicking the label toggles the checkbox which triggers .info:has() to hide the panel.
  • This is a creative way to build a close button that works without JavaScript.

12. Responsive Design

  • Controls and info blocks have max-widths based on viewport widths (min(60rem, 100vw - 10rem)) for good responsiveness.
  • Controls layout uses grid-template-columns: repeat(auto-fill, minmax(auto, 1fr)) to adapt buttons or blocks dynamically.

Summary

This CSS uses modern CSS features at an expert level to create a 3D interactive voxel-style UI while minimizing or eliminating JavaScript:

  • CSS custom properties for configuration and theming.
  • :has() pseudo-class for conditional styling and interaction states.
  • CSS animations triggered by :active state and controlled with animation-play-state.
  • 3D transforms and perspective for cube rendering.
  • Pixelated background images producing Minecraft-like textures.
  • Smart use of hidden radio inputs for UI state control.
  • Backdrop blur, responsive design, and accessibility tricks with input/label controls.

The result is a responsive, interactive 3D block builder fully implemented in CSS.


Feel free to ask if you want a detailed explanation of any particular part!

Token usage

3,813 input, 1,291 output

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment