> All in One 586

Ads

Sunday, August 31, 2025

Clear today!



With a high of F and a low of 54F. Currently, it's 63F and Clear outside.

Current wind speeds: 4 from the Southeast

Pollen: 0

Sunrise: August 31, 2025 at 06:19PM

Sunset: September 1, 2025 at 07:23AM

UV index: 0

Humidity: 65%

via https://ift.tt/tky2omb

September 1, 2025 at 10:02AM

Saturday, August 30, 2025

Thunderstorms Early today!



With a high of F and a low of 53F. Currently, it's 59F and Clear outside.

Current wind speeds: 5 from the Northwest

Pollen: 0

Sunrise: August 30, 2025 at 06:18PM

Sunset: August 31, 2025 at 07:25AM

UV index: 0

Humidity: 83%

via https://ift.tt/orIEstg

August 31, 2025 at 10:02AM

Friday, August 29, 2025

Thunderstorms today!



With a high of F and a low of 57F. Currently, it's 64F and Cloudy outside.

Current wind speeds: 10 from the Southwest

Pollen: 0

Sunrise: August 29, 2025 at 06:17PM

Sunset: August 30, 2025 at 07:26AM

UV index: 0

Humidity: 85%

via https://ift.tt/UJiw1Hy

August 30, 2025 at 10:02AM

CSS Elevator: A Pure CSS State Machine With Floor Navigation

As a developer with a passion for state machines, I’ve often found myself inspired by articles like “A Complete State Machine Made with HTML Checkboxes and CSS.” The power of pure CSS-driven state machines intrigued me, and I began to wonder: could I create something simpler, more interactive, and without the use of macros? This led to a project where I built an elevator simulation in CSS, complete with direction indicators, animated transitions, counters, and even accessibility features.

In this article, I’ll walk you through how I used modern CSS features — like custom properties, counters, the :has() pseudo-class, and @property — to build a fully functional, interactive elevator that knows where it is, where it’s headed, and how long it’ll take to get there. No JavaScript required.

Defining the State with CSS Variables

The backbone of this elevator system is the use of CSS custom properties to track its state. Below, I define several @property rules to allow transitions and typed values:

@property --current-floor {
  syntax: "<integer>";
  initial-value: 1;
  inherits: true;
}

@property --previous {
  syntax: "<number>";
  initial-value: 1;
  inherits: true;
}

@property --relative-speed {
  syntax: "<number>";
  initial-value: 4;
  inherits: true;
}

@property --direction {
  syntax: "<integer>";
  initial-value: 0;
  inherits: true;
}

These variables allow me to compare the elevator’s current floor to its previous one, calculate movement speed, and drive animations and transitions accordingly.

A regular CSS custom property (--current-floor) is great for passing values around, but the browser treats everything like a string: it doesn’t know if 5 is a number, a color, or the name of your cat. And if it doesn’t know, it can’t animate it.

That’s where @property comes in. By “registering” the variable, I can tell the browser exactly what it is (<number>, <length>, etc.), give it a starting value, and let it handle the smooth in-between frames. Without it, my elevator would just snap from floor to floor,  and that’s not the ride experience I was going for.

A Simple UI: Radio Buttons for Floors

Radio buttons provide the state triggers. Each floor corresponds to a radio input, and I use :has() to detect which one is selected:

<input type="radio" id="floor1" name="floor" value="1" checked>
<input type="radio" id="floor2" name="floor" value="2">
<input type="radio" id="floor3" name="floor" value="3">
<input type="radio" id="floor4" name="floor" value="4">
.elevator-system:has(#floor1:checked) {
  --current-floor: 1;
  --previous: var(--current-floor);
}

.elevator-system:has(#floor2:checked) {
  --current-floor: 2;
  --previous: var(--current-floor);
}

This combination lets the elevator system become a state machine, where selecting a radio button triggers transitions and calculations.

Motion via Dynamic Variables

To simulate elevator movement, I use transform: translateY(...) and calculate it with the --current-floor value:

.elevator {
  transform: translateY(calc((1 - var(--current-floor)) * var(--floor-height)));
  transition: transform calc(var(--relative-speed) * 1s);
}

The travel duration is proportional to how many floors the elevator must traverse:

--abs: calc(abs(var(--current-floor) - var(--previous)));
--relative-speed: calc(1 + var(--abs));

Let’s break that down:

  • --abs gives the absolute number of floors to move.
  • --relative-speed makes the animation slower when moving across more floors.

So, if the elevator jumps from floor 1 to 4, the animation lasts longer than it does going from floor 2 to 3. All of this is derived using just math expressions in the CSS calc() function.

Determining Direction and Arrow Behavior

The elevator’s arrow points up or down based on the change in floor:

--direction: clamp(-1, calc(var(--current-floor) - var(--previous)), 1);

.arrow {
  scale: calc(var(--direction) * 2);
  opacity: abs(var(--direction));
  transition: all 0.15s ease-in-out;
}

Here’s what’s happening:

  • The clamp() function limits the result between -1 and 1.
  • 1 means upward movement, -1 is downward, and 0 means stationary.
  • This result is used to scale the arrow, flipping it and adjusting its opacity accordingly.

It’s a lightweight way to convey directional logic using math and visual cues with no scripting.

Simulating Memory with --delay

CSS doesn’t store previous state natively. I simulate this by delaying updates to the --previous property:

.elevator-system {
  transition: --previous calc(var(--delay) * 1s);
  --delay: 1;
}

While the delay runs, the --previous value lags behind the --current-floor. That lets me calculate direction and speed during the animation. Once the delay ends, --previous catches up. This delay-based memory trick allows CSS to approximate state transitions normally done with JavaScript.

Floor Counters and Unicode Styling

Displaying floor numbers elegantly became a joy thanks to CSS counters:

#floor-display:before {
  counter-reset: display var(--current-floor);
  content: counter(display, top-display);
}

I defined a custom counter style using Unicode circled numbers:

@counter-style top-display {
  system: cyclic;
  symbols: "\278A" "\2781" "\2782" "\2783";
  suffix: "";
}

The \278A to \2783 characters correspond to the ➊, ➋, ➌, ➃ symbols and give a unique, visual charm to the display. The elevator doesn’t just say “3,” but displays it with typographic flair. This approach is handy when you want to go beyond raw digits and apply symbolic or visual meaning using nothing but CSS.

Unicode characters replacing numbers 1 through 4 with circled alternatives

Accessibility with aria-live

Accessibility matters. While CSS can’t change DOM text, it can still update screenreader-visible content using ::before and counter().

<div class="sr-only" aria-live="polite" id="floor-announcer"></div>
#floor-announcer::before {
  counter-reset: floor var(--current-floor);
  content: "Now on floor " counter(floor);
}

Add a .sr-only class to visually hide it but expose it to assistive tech:

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

This keeps the experience inclusive and aligned with accessibility standards.

Practical Applications of These Techniques

This elevator is more than a toy. It’s a blueprint. Consider these real-world uses:

  • Interactive prototypes without JavaScript
  • Progress indicators in forms using live state
  • Game UIs with inventory or status mechanics
  • Logic puzzles or educational tools (CSS-only state tracking!)
  • Reduced JavaScript dependencies for performance or sandboxed environments

These techniques are especially useful in static apps or restricted scripting environments (e.g., emails, certain content management system widgets).

Final Thoughts

What started as a small experiment turned into a functional CSS state machine that animates, signals direction, and announces changes, completely without JavaScript. Modern CSS can do more than we often give it credit for. With :has(), @property, counters, and a bit of clever math, you can build systems that are reactive, beautiful, and even accessible.

If you try out this technique, I’d love to see your take. And if you remix the elevator (maybe add more floors or challenges?), send it my way!


CSS Elevator: A Pure CSS State Machine With Floor Navigation originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.



from CSS-Tricks https://ift.tt/6gewxEX
via IFTTT

Thursday, August 28, 2025

Partly Cloudy today!



With a high of F and a low of 59F. Currently, it's 64F and Heavy Thunderstorm outside.

Current wind speeds: 9 from the Southeast

Pollen: 0

Sunrise: August 28, 2025 at 06:16PM

Sunset: August 29, 2025 at 07:28AM

UV index: 0

Humidity: 88%

via https://ift.tt/OmzeM1j

August 29, 2025 at 10:02AM

Wednesday, August 27, 2025

Thunderstorms Early today!



With a high of F and a low of 57F. Currently, it's 63F and Showers in the Vicinity outside.

Current wind speeds: 9 from the Northeast

Pollen: 0

Sunrise: August 27, 2025 at 06:15PM

Sunset: August 28, 2025 at 07:29AM

UV index: 0

Humidity: 96%

via https://ift.tt/6o7Ht0Z

August 28, 2025 at 10:02AM

A Radio Button Shopping Cart Trick

Editor’s note: This is a really clever idea that Preethi shared, but you will also see that it comes with accessibility drawbacks because it uses duplicated interactive elements. There are other ways to approach this sort of thing, as Preethi mentions, and we’ll look at one of them in a future article.

Two large pizzas for yourself, or twelve small ones for the kids party — everyone’s gone through the process of adding items to an online cart. Groceries. Clothing. Deli orders. It’s great when that process is simple, efficient, and maybe even a little quirky.

This post covers a design referred as infinite selection. Metaphorically infinite.

Here’s how it works:

That’s right, you click an item and it jumps right into the shopping cart, complete with a smooth transition that shows it happening. You can add as many items as you want!

And guess what: all of it is done in CSS — well, except the part that keeps count of selected items — and all it took is a combination of radio form inputs in the markup.

I’m going to walk you through the code, starting with the layout, but before that, I want to say up-front that this is just one approach. There are for sure other ways to go about this, and this specific way comes with its own considerations and limitations that we’ll get into.

The Layout

Each item (or product, whatever you want to call it) is a wrapper that contains two radio form inputs sharing the same name value — a radio group.

<div class="items flat-white">
  <input type="radio" name="r3" title="Flat White">
  <input type="radio" name="r3" title="Flat White">
</div>

When you check one in a duo, the other gets unchecked automatically, leading to a see-saw of check and uncheck between the two, no matter which one is clicked.

Each item (or radio group) is absolutely positioned, as are the two inputs it contains:

.items {   
  position: absolute;

  input { 
    position: absolute; 
    inset: 0; 
  }
}

The inset property is stretching the inputs to cover the entire space, making sure they are clickable without leaving any dead area around them.

Now we arrange everything in a layout. We’ll use translate to move the items from a single point (where the centered cart is) to another point that is a litte higher and spread out. You can code this layout anyway you like, as long as the radio buttons inside can make their way to the cart when they are selected.

.items {
  --y: 100px; /* Vertical distance from the cart */

  &:not(.cart) {
    transform: translate(var(--x), calc(-1 * var(--y)));
  }
  &.espresso { 
    --x: 0px;  /* Horizontal dist. from the cart */
  }
  &.cappuccino { 
    --x: -100%; 
  }
  &.flat-white { 
    --x: 100%; 
  }
}

So, yeah, a little bit of configuration to get things just right for your specific use case. It’s a little bit of magic numbering that perhaps another approach could abstract away.

Selecting Items

When an item (<input>) is selected (:checked), it shrinks and moves (translate) to where the cart is:

input:checked {
  transform: translate(calc(-1 * var(--x)), var(--y)) scale(0);
}

What happens under the hood is that the second radio input in the group is checked, which immediately unchecks the first input in the group, thanks to the fact that they share the same name attribute in the HTML. This gives us a bit of boolean logic a là the Checkbox Hack that we can use to trigger the transition.

So, if that last bit of CSS moves the selected item to the shopping cart, then we need a transition to animate it. Otherwise, the item sorta zaps itself over, Star Trek style, without you telling.

input:checked{
  transform: translate(calc(-1 * var(--x)), var(--y)) scale(0);
  transition: transform .6s linear;
}

Keeping Count

The whole point of this post is getting a selected item to the cart. There’s no “Cart” page to speak of, at least for the purposes of this demo. So, I thought it would be a good idea to show how many items have been added to the cart. A little label with the count should do the trick.

let n = 0;
const CART_CNT = document.querySelector("output");
document.querySelectorAll("[type='radio']").forEach(radio => {
  radio.onclick = () => {
    CART_CNT.innerText = ++n;
    CART_CNT.setAttribute("arial-label", `${n}`)
  }
});

Basically, we’re selecting the cart object (the <output> element) and, for each click on a radio input, we increase an integer that represents the count, which is slapped onto the shopping card icon as a label. Sorry, no removing items from the cart for this example… you’re completely locked in. 😅

Accessibility?

Honestly, I wrestled with this one and there probably isn’t a bulletproof way to get this demo read consistently by screen readers. We’re working with two interactive elements in each group, and need to juggle how they’re exposed to assistive tech when toggling their states. As it is, there are cases where one radio input is read when toggling into an item, and the other input is read when toggling back to it. In other cases, both inputs in the groups are announced, which suggests multiple options in each group when there’s only one.

I did add a hidden <span> in the markup that is revealed with keyboard interaction as a form of instruction. I’ve also inserted an aria-label on the <output> that announces the total number of cart items as they are added.

Here’s the final demo once again:

Maybe Use View Transitions Instead?

I wanted to share this trick because I think it’s a clever approach that isn’t immediately obvious at first glance. But this also smells like a situation where the modern View Transition API might be relevant.

Adrian Bece writes all about it in a Smashing Magazine piece. In fact, his example is exactly the same: animating items added to a shopping cart. What’s nice about this is that it only takes two elements to build the transition: the item and the cart label. Using CSS, we can hook those elements up with a view-transition-name, define a @keyframes animation for moving the item, then trigger it on click. No duplicate elements or state juggling needed!

Alternatively, if you’re working with just a few items then perhaps a checkbox input is another possible approach that only requires a single element per item. the downside, of course, is that it limits how many items you can add to the card.

But if you need to add an infinite number of items and the View Transition API is out of scope, then perhaps this radio input approach is worth considering.


A Radio Button Shopping Cart Trick originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.



from CSS-Tricks https://ift.tt/rkp8qDK
via IFTTT

What Can We Actually Do With corner-shape?

When I first started messing around with code, rounded corners required five background images or an image sprite likely created in Photosh...