> All in One 586

Ads

Thursday, May 14, 2026

Partly Cloudy today!



With a high of F and a low of 51F. Currently, it's 65F and Clear outside.

Current wind speeds: 8 from the Northeast

Pollen: 4

Sunrise: May 14, 2026 at 05:39PM

Sunset: May 15, 2026 at 07:57AM

UV index: 0

Humidity: 44%

via https://ift.tt/BtdusDa

May 15, 2026 at 10:02AM

Computing and Displaying Discounted Prices in CSS

CSS math isn’t just about how things look! It can also be used to work out useful numeric information. For instance, you could calculate and show the percentage of tasks completed in a to-do list with CSS, helping users keep track of their progress. No need for script or server computation. No latency. No use of additional browser resources.

Working with math has become much simpler and more flexible. I’m going to give you an example using CSS to calculate and display a discounted price whenever you need it, using the base price and discount provided. It’s the sort of thing you see often on e-commerce sites where heavy JavaScript is used to show a product’s full price, its discount amount, and its sale price.

A four column row of product cards showing sale clothing from Gap. Model photos are on top, followed by the product name, price, and sale price.
Screenshot taken from gap.com

We can absolutely do that in CSS:

It does rely on some bleeding-edge features that are waiting to gain more browser support, but I think it’s still a good exercise to dig into how we will eventually be able to put these things in practice and eventually use them in our everyday work.

Here’s how I put it together.

The initial markup

The interface in this specific demo displays a list of streaming services for the user to choose from — Netflix, Disney+, HBO, HBO Now, HBO Go, HBO Max, etc. There’s a student discount offer on each subscription that takes a certain percentage amount off the full price.

<li>
  <!-- Service name, base price, and selection toggle -->
  <label>
    <span>Netflix</span>
    <!-- data-price and data-discount store base price and discount offered -->
    <div class="ott-price" data-price="7.99" data-discount="0.2">$7.99</div>
    <!-- Checkbox to track if the user wants to add this service -->
    <input type="checkbox" class="is-ott-selected">
  </label>

  <!-- Toggle for the student discount -->
  <label>
    <span>Apply Student Discount <br> 20%</span>
    <input type="checkbox" class="is-ott-discounted">
  </label>
</li>

<!-- etc. -->

The base price and discount are included as data-* attributes in the element displaying the price. Just remember, the discount only kicks in when you select “Apply Student Discount,” and then you’ll see how much the price is after the discount is applied.

Calculating the price cut

When the discount kicks in, the first step is to slash the base price with a line across it.

/* When the discount toggle is checked inside the .ott container */
.ott:has(.is-ott-discounted:checked) {
  /* Strike through the original price */
  .ott-price {
    text-decoration: line-through;
  }
}

Next, let’s figure out the new discounted price using the data-price and data-discount values.

.ott:has(.is-ott-discounted:checked) {
  .ott-price {
    text-decoration: line-through;
    /* 
        Calculate the new price from the data-* attributes:
        Original Price * (1 - Discount Applied)
    */
    --n: calc(attr(data-price number) * (1 - attr(data-discount number)));
  }
}

The attr(<name> <type>) syntax is relatively new. The function used to only work with the content property, but now supports any CSS property… and parses values into a range of data types, whereas before they were always parsed as strings.

Those arguments:

  1. <name>: This is the name of the HTML attribute we want to look at (like href, data-count, or title).
  2. <type>: This tells CSS how to “read” the value (like a color, a number, or a length). It’s the newer superpower that makes the work we’re doing here possible.

In our case, we’re using the function to parse both data-price and data-discount into numbers, and then we subtract the discount from the price with CSS math-iness.

The upgraded attr() is super cool, but not Baseline as I’m writing this, so keep an eye on it.

Showing the discounted price

Here’s how we display the updated price once the discount is applied:

.ott:has(.is-ott-discounted:checked) {
  .ott-price {
    text-decoration: line-through;
    --n: calc(attr(data-price number) * (1 - attr(data-discount number)));

    &::after {
      display: inline-block;
      /* Splits the variable --n into two counters: 
          'a' for the whole number (in dollars) and 'b' for the decimals (in cents) */
      counter-set: a calc(round(down, var(--n))) b calc((mod(var(--n), 1)) * 100);
      /* Output: two spaces (\2000), a dollar sign ($), the number, a dot, and the decimals */
      content: "\2000\2000$" counter(a) "." counter(b, decimal-leading-zero);
    }
  }
}

The counter() function helps us turn the numeric value of the --n varable into a content string. Since CSS counters can’t handle decimals (they round the value by default), we treat the numbers before and after the decimal as separate counters and then combine them as strings, adding a dot between them.

  1. calc(round(down, var(--n))) takes the variable --n and rounds it down to get the whole dollar amount (stored as counter(a)).
  2. calc((mod(var(--n), 1)) * 100) uses the modulo mod() function to isolate the fraction, then multiplies it by 100 to get the cents (stored as counter(b)).
  3. The content property inserts a dollar sign before the two counters and then joins them with a dot.

We know that calc() has plenty of browser support. And guess what? The mod() function is newly Baseline!

That’s only if you need decimals and all that. If you’re rounding prices, this would be plenty enough:

counter-set: price calc(var(--n));
content: counter(price);

Here’s the demo once again:

Wrapping up

So, there we have it, a working combination of newer CSS features (the upgraded attr() function), CSS math functions (mod(), round()), and custom counters to nail down something that we see in so many websites, only without scripts. When attr()‘s support for data types becomes a thing in all browsers, this is something you can use in your everyday work.


Computing and Displaying Discounted Prices in CSS originally handwritten and published with love on CSS-Tricks. You should really get the newsletter as well.



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

Wednesday, May 13, 2026

Partly Cloudy today!



With a high of F and a low of 57F. Currently, it's 69F and Fair outside.

Current wind speeds: 17 from the Southeast

Pollen: 0

Sunrise: May 13, 2026 at 05:40PM

Sunset: May 14, 2026 at 07:56AM

UV index: 0

Humidity: 35%

via https://ift.tt/w8F3fcp

May 14, 2026 at 10:02AM

rotate()

The CSS rotate() function spins an element either clockwise or counterclockwise in a 2D plane. It is one of many transform functions used in the transform property.

For example, using rotate() we can rotate the hand around the clock:

.seconds-hand {
  transform: rotate(var(--deg));
  transform-origin: bottom center;
}

For rotating elements tri-dimensionally, consider using rotateX() and rotateY().

The rotate() functions is defined in the CSS Transforms Module Level 1 specification.

Syntax

rotate() = rotate( [ <angle> | <zero> ] )

Arguments

/* <angle> */
rotateZ(90deg) /* Rotates 90 degrees clockwise  */
rotateZ(-180deg) /* Rotates 180 degrees counterclockwise */

/* <angle> in turns */
rotateZ(0.25turn) /* Rotates a quater turn clockwise. */
rotateZ(1turn)    /* Rotates a full 360-degree turn. */

/* <angle> in radians */
rotateZ(1.57rad)  /* Rotates ~90 degrees clockwise. */
rotateZ(-3.14rad) /* Rotate ~180 degrees counterclockwise. */

The rotate() function accepts a single <angle> argument, which dictates the direction of its spin. A positive argument spins the element clockwise, while a negative argument spins the element counterclockwise.

The <angle> type has four units to choose from:

  • deg: One degree is 1/360 of a full circle.
  • grad: One gradian is 1/400 of a full circle.
  • rad: A radian is the length of a circle’s diameter around the shape’s arc. One radian is 180deg, or 1/2 of a full circle. One full circle is 2π radians, which is equal to 6.2832rad or 360deg.
  • turn: One turn is one full circle. So, halfway around a circle is equal to .5turn, or 180deg.

Also, rotate() spins the element around its center axis. To change the rotation point, we have to pass a specific point to the transform-origin property that’ll serve as the axis of rotation.

Basic usage

The rotate() function is the backbone of some of the basic animations you’ve most likely come across on, like switching from “+” to “x” when an accordion is opened. We can do that by rotating the “+” symbol by 45deg.

So, if we have a button like this:

<button class="toggle">
  <span class="icon">+</span>
  <span class="label">Open Section</span>
</button>

We can sprinkle a little JavaScript in there to trigger an .active class when the button is clicked, which rotates the icon:

.toggle.active .icon {
  transform: rotate(45deg);
}

Example: Hamburger menu

Have you seen those menus that switch from a hamburger icon to a closing “X” icon when a menu dropdown or sidebar is opened? That’s a rotation, too!

We start with three spans that are styled as horizontal lines:

<button class="hamburger" id="hamburgerBtn">
  <span class="bar top"></span>
  <span class="bar middle"></span>
  <span class="bar bottom"></span>
</button>
.bar {
  width: 100%;
  height: 4px;
  background: #333;
  transition: transform 0.3s ease, opacity 0.3s ease;
}

Notice we have a transition in there so that, when the button is clicked and the rotation happens (again, using JavaScript to toggle on an .active class), the spans transform smoothly:

.hamburger.active .top {
  transform: translateY(14px) rotate(45deg);
}

.hamburger.active .middle {
  opacity: 0;
}

.hamburger.active .bottom {
  transform: translateY(-14px) rotate(-45deg);
}

Example: Loading icons

We can also use rotate() for loading indicators. Loading indicators usually spin while a page is, you know, loading. A common example is a semi-circle that spins until the page is done loading.

The .spinner uses the CSS animation shorthand to define an infinite spinning loading indicator, and the @keyframes spin defines a 360deg spin with the rotate() function.

.spinner {
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

Now the spinner keeps on a’spinning:

Example: Rotating text

Rotating things isn’t always about animation! We can, for example, position something like a “Feature” label next to a blog post and rotate it vertically for an interesting visual effect.

.vertical-header {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
}

Demo

Let’s look at a more complex animation to demonstrate just how neat it is to rotate() things with CSS. If you “Rerun” the demo, you’ll see the photo swing back and forth. You can also drag the photo from left to right to rotate it.

Specification

The CSS rotate() function is defined in the CSS Transforms Module Level 1 specification, which is currently in Editor’s Draft.

Browser support


rotate() originally handwritten and published with love on CSS-Tricks. You should really get the newsletter as well.



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

Tuesday, May 12, 2026

Clear today!



With a high of F and a low of 47F. Currently, it's 60F and Clear outside.

Current wind speeds: 8 from the East

Pollen: 0

Sunrise: May 12, 2026 at 05:41PM

Sunset: May 13, 2026 at 07:55AM

UV index: 0

Humidity: 41%

via https://ift.tt/jsi2ekA

May 13, 2026 at 10:02AM

Soon We Can Finally Banish JavaScript to the ShadowRealm

It’s gonna be tough to keep it together on this one. Okay. I got this. I am a professional technical writer. Straight face; all-business. Ahem: if you’ve been following the ongoing work at TC39 (the standards body responsible for maintaining and developing the standards that inform JavaScript) you may have encountered some of their recent work on ShadowRealmssnrk. Sorry! Sorry, I’m good! Just, whew ­— what a name, “ShadowRealms.” Okay, hang on, let me start at the beginning. Maybe that will help.

It’s exceptionally likely you’ve seen JavaScript described as “single-threaded” at some point — that’s usually pretty high up on the list of JavaScript fundamentals, alongside “case sensitive,” “whitespace insensitive,” and “bad at math.” That is correct, in the strict “computer science” sense, but it still gets my hackles up a little whenever I see it.

I mean, accurate in that JavaScript isn’t multi-threaded, for sure. A script is always executed in a very linear way — top to bottom, left to right, one execution context after another, winding up the call stack and then back down again. It’s just that you eventually come to learn about something like Web Workers, which — not to put too fine a point on this — allow you to execute JavaScript code in another thread. That’s where I think “JavaScript is single-threaded” becomes a less helpful framing, because even though JavaScript isn’t a multi-threaded language, a JavaScript application can make use of multiple threads.

It’s a better framing — and every bit as technically accurate — to say that a JavaScript realm is single-threaded. A realm refers to the environment where code is executed: a browser tab is a realm, and within that realm is the single thread where JavaScript is executed — the main thread. A Web Worker is a realm with a worker thread. JavaScript running in a cross-origin iframe is running in that iframe realm’s main thread. We can’t, for example, offload the execution of a single function to another thread — JavaScript is itself single-threaded, as a language. But a JavaScript application can span multiple realms and make use of multiple execution threads, and each of those realms can communicate with other realms in specific ways.

Each JavaScript realm has its own global environment. In a browser tab, the global object is the Window interface. The same is true in a non-same-origin iframe within that browser tab — the global object is the Window “owned” by that iframe:

<html>
  <head></head>
  <body>
    <iframe id="theIframe"></iframe>
  </body>

  <script>
  ( () => {
    console.log( window.globalThis );
    // Result: Window {}

    console.log( theIframe.contentWindow.globalThis );
    // Result: Window {}
  })();

  </script>
</html>

These aren’t the same global object:

<html>
  <head></head>
  <body>
    <iframe id="theIframe"></iframe>
  </body>

  <script>
  ( () => {
    console.log( window.globalThis === theIframe.contentWindow.globalThis );
    // Result: false
  })();
  </script>
</html>

The outer page and the inner iframe are two separate realms, both single-threaded, each with their own global objects and their own intrinsic objects:

<html>
  <head></head>
  <body>
    <iframe id="theIframe"></iframe>
  </body>

  <script>
    (() => {
      console.log( window.Array );
      /* Result (expanded):
        function Array()
        from: function from()
        fromAsync: function fromAsync()
        isArray: function isArray()
        length: 1
        name: "Array"
        of: function of()
        prototype: Array []
        Symbol(Symbol.species): undefined
        <prototype>: function ()
      */

      console.log( theIframe.contentWindow.Array );
      /* Result (expanded):
        function Array()
        from: function from()
        fromAsync: function fromAsync()
        isArray: function isArray()
        length: 1
        name: "Array"
        of: function of()
        prototype: Array []
        Symbol(Symbol.species): undefined
        <prototype>: function ()
      */

      console.log( window.Array === theIframe.contentWindow.Array );
      // Result: false

    })();
  </script>
</html>

So, as you might expect, any global properties defined in the context of one realm will be unavailable to another:

<html>
  <head></head>
  <body>
    <iframe id="theIframe"></iframe>
  </body>

  <script>
  function globalFunction() {};

  console.log( window.globalFunction );
  // Result: function globalFunction()

  console.log( theIframe.contentWindow.globalFunction );
  // Result: undefined
  </script>
</html>

“Unavailable” — or, depending on how you look at it, unable to interfere with the the global object of another realm. If you’ve been JavaScripting for a while, you know that no matter how meticulous we are about managing scope, the global environment can get pretty messy despite our best efforts. Some of that is on us, sure — a stray variable binding happens to the best of us — but a lot of that clutter is a result of the early design decisions that went into the language itself, like the function declaration in the previous example. When you consider the staggering amount of JavaScript we don’t control that can get piled onto the average project — from frameworks to third-party helper libraries to polyfills to user analytics to advertisements — there’s potential for collisions, to say the least.

Given the global scope pollution that has haunted the language since time immemorial (the 90s), it isn’t hard to imagine the use cases for offloading code to a realm that can act as a sandbox for the execution of JavaScript we don’t want to impact, or be impacted by, whatever is already cluttering up the global scope. We might want to run part of our test suite in a “clean room” where performing the testing can’t potentially interfere with the results of your testing and mock data can’t run afoul of the real thing, or a place to run code we want quarantined away from the realm that contains our JavaScript application itself to prevent third-party libraries that don’t need access to the global environment from cluttering it up, to no benefit.

We can’t do that with realms, as they stand right now — remember, JavaScript is single-threaded in that each realm is single-threaded, and communication between those threads is limited. As undeniable as the use case is, we can’t repurpose an alternate realm to execute code on its single thread of execution, then weave the results of that execution back into the main thread of our primary realm. That’s multi-threaded execution by definition, and not just contrary to the fundamental nature of JavaScript, but, well, let me put it this way: JavaScript allowing multiple threads of execution at the same time mean would problems us new for.

To offload code in this way would require a new kind of realm — one that has its own global and intrinsic objects, but not it’s own thread — a realm where code offloaded to it will still be executed on the main thread of the realm that “owns” that script. A dark reflection of our own realms; a realm the light can never touch, where only fleeting, ephemeral shadows of our banished code can dwell! Imagine a distant peal of thunder, here; maybe also imagine that I’m wearing a cape, maybe I hurl a wine glass to the floor. Y’know, have fun with it. How could you not? I mean, they’re called:

ShadowRealms

The proposed ShadowRealm API introduces a new kind of realm specifically designed for isolation, and only that. A ShadowRealm does not have an execution context of its own — code offloaded to a ShadowRealm will exist in a pseudo-realm with its own global and built-in objects. That code continues to run on the same thread as the code where the ShadowRealm is created; we’re not forced to communicate and share resources back and forth between two separate threads in limited ways. In short, a script is executed the way it would if limited to a single realm, but quarantined away from that outer realm’s intrinsic objects, APIs, global object, and anything our script has done to that global object.

That sounds complicated, but the proposed API would be exceptionally simple in practice:

// Create a ShadowRealm:
const shadow = new ShadowRealm();

function globalFunction() {};

console.log( globalthis.globalFunction );
// Result: function globalFunction()

// Evaluate `globalThis.globalFunction` inside the ShadowRealm:
console.log( shadow.evaluate( 'globalThis.globalFunction' ) );
// Result: undefined

Note: Keep in mind that this code is still theoretical — it doesn’t exist in the ES-262 standard or browsers just yet.

globalFunction is defined on the outer realm’s global object just like we saw earlier, but it isn’t defined on the global object inside of our newly-created ShadowRealm — that ShadowRealm’s global object remains pristine, no matter what we do outside of it. The inverse is true, naturally:

// Create a ShadowRealm:
const shadow = new ShadowRealm();

// Declare a global function inside the ShadowRealm:
shadow.evaluate( 'function globalFunction() {};' );

// It doesn't exist in the outer realm's global object:
console.log( globalthis.globalFunction );
// Result: undefined

// But when we evaluate `globalThis.globalFunction` inside the ShadowRealm:
console.log( shadow.evaluate( 'globalThis.globalFunction' ) );
// Result: function globalFunction()

We’ve declared that function inside the ShadowRealm, and we can call it by way of the variable that references that ShadowRealm object. That function remains quarantined away from the outer global object and that of any other ShadowRealm:

// Create a ShadowRealm:
const firstShadow = new ShadowRealm();
const secondShadow = new ShadowRealm();

// Declare a global function inside the ShadowRealm referenced by `secondShadow`:
secondShadow.evaluate( 'function globalFunction() {};' );

// It doesn't exist in the outer realm's global object:
console.log( globalthis.globalFunction );
// Result: undefined

// It doesn't exist in the global object of the ShadowRealm referencd by `firstShadow`:
console.log( firstShadow.evaluate( 'globalThis.globalFunction' ) );
// Result: undefined

// It only exists within the ShadowRealm referenced by `secondShadow`:
console.log( secondShadow.evaluate( 'globalThis.globalFunction' ) );
// Result: function globalFunction()

“Quarantined” to an extent, that is. ShadowRealms don’t provide a true security boundary in that code running inside a ShadowRealm can still make inferences about code running in other realms. They can be thought of as an integrity boundary, in that code running inside a ShadowRealm can’t directly interfere with another realm — unless we let it, of course. Even though code shunted off into a ShadowRealm can’t interfere with the objects outside of it, we’re still free to use the results of those operations the way we would use the results of that same operation in the host realm:

// Create a ShadowRealm:
const shadow = new ShadowRealm();

// Create a binding that calls a function inside the ShadowRealm:
const shadowFunction = shadow.evaluate( '( value ) => globalThis.someValue = value );

// ...and call our wrapped function using that binding:
shadowFunction( "Hello from the ShadowRealm!" );

// Executing this function in the host realm doesn't _change_ anything here, of course:
console.log( globalThis.someValue );
// Result: undefined

// But we can grab the result from the ShadowRealm:
const shadowValue = shadow.evaluate( 'globalThis.someValue' );

// And use it here in the host realm:
console.log( shadowValue );
// Result: Hello from the ShadowRealm!

Infinite disposable cleanrooms! Pocket dimensions where we can execute whatever code we want, without fear of that code interfering with the scope of any other ShadowRealm or the outer realm — the “light realm,” if you will.

Now, some of you — especially those of you who’ve been doing this since the early days of JavaScript — have probably been recoiling at these examples. You’d be forgiven for thinking that ShadowRealm API is just goth eval, and you wouldn’t be strictly wrong: apart from running in the context of a ShadowRealm, what you’ve seen so far here are basically indirect calls to eval — even subject to the same unsafe-eval Content Security Policy rule.

Fear not for your workflows, however: while these are illustrative examples, this isn’t the only way to put ShadowRealms to use. The proposal includes an importValue method on the ShadowRealm object’s prototype, which allows you to dynamically import modules, then capture and work with exported values and functions:

// spookycode.js
export function greeting() {
 return "Hello from the ShadowRealm!";
}
async function shadowGreeter() {
  // I INVOKE THE DARK POWER OF THE SHADOWREALM- ahem. Sorry.
  const shadow = new ShadowRealm();

  /* 
  * `importValue` returns a promise that resolves with the value of the function 
  * specified in the second argument: 
  */
  const shadowGreet = await shadow.importValue( "./spookycode.js", "greeting" );

  // Call our wrapped function, annnnd...
  shadowGreet();
}

shadowGreeter();
// Result: Hello from the ShadowRealm!

The shadow hasn’t fallen yet

I’m pleased to say that you’ve now seen the entirety of the proposed ShadowRealms API, at this point. The proposal includes only those the two methods you’ve seen here — evaluate and importValue — both means of banishing evaluating code in the context of a ShadowRealm instance while still executing that code in the context of the host realm’s thread.

Again, though: none of this can be put to use just yet. The proposed specification is currently at Stage 2.7 — “approved in principle and undergoing validation,” meaning that it’s only likely to change as a result of feedback from tests and trial implementations in browsers, if at all. You’re playing a move ahead by reading this. When this proposal reaches Stage 3 and we start to see implementations in browsers, you’ll be ready to try it out for yourself. Nay, more than ready — at such time as the awesome power of the ShadowRealm is loosed upon the web, you shall stand at the ready to command its dark and fearsome majjycks! The very realm upon which our code stands shall quake, as— okay, okay, sorry. Look, I can’t help it! I mean, “ShadowRealm,” for cryin’ out loud.


Soon We Can Finally Banish JavaScript to the ShadowRealm originally handwritten and published with love on CSS-Tricks. You should really get the newsletter as well.



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

Monday, May 11, 2026

Clear today!



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

Current wind speeds: 10 from the South

Pollen: 0

Sunrise: May 11, 2026 at 05:42PM

Sunset: May 12, 2026 at 07:54AM

UV index: 0

Humidity: 34%

via https://ift.tt/HJnNqlh

May 12, 2026 at 10:02AM

Partly Cloudy today!

With a high of F and a low of 51F. Currently, it's 65F and Clear outside. Current wind speeds: 8 from the Northeast Pollen: 4 Su...