picocss / pico

Minimal CSS Framework for semantic HTML
https://picocss.com
MIT License
13.82k stars 406 forks source link

Fix input switch inconsistency #472

Closed FireIsGood closed 8 months ago

FireIsGood commented 8 months ago

Fixes #467

Previously, the switch :checked:before was incorrectly offset by an approximation using the switch's width and border sizes. This changes them to use the units correctly.

I have also rebuilt all the CSS, however you may undo that commit and rebuild yourself if you wish.

Comparison

Before:

image

After:

image

Info for CSS nerds

If you wanted to know why the units were wrong and how they were changed:

Here's the technical stuff
The issue was that the previous version was only using the SCSS variable `$switch-width` and then approximating by dividing it by two, then subtracting the border width. The issue with this approach is that the dot ends up being aligned to the center right side. What the code used to do was: 1. Get half the width of the interior box (`switch-width * 0.5 - border-width`) Since this never accounts for the button's size, this method can never work with other knob sizes. ![image](https://github.com/picocss/pico/assets/109556932/0315d8ca-e903-429b-aa0b-193531355780) To fix this, we can instead get the full width and then offset based on the button's size before combining them. What the code does now: 1. Get the full width of the interior box (`switch-width - border-width * 2`) 2. Offset by the button width (`- switch-height * 0.5 - border-width` (knob width is equal to half the switch height minus the borders)) Combined, this turns into `switch-width - switch-height / 2 - border-width * 3`. ![image](https://github.com/picocss/pico/assets/109556932/c9b4c171-165d-49dc-aa6d-cf73d1469c4e) So yeah.
FireIsGood commented 8 months ago

This pull request separately calculates the variables switch-width and switch-height when doing the left offset from the button to be more transparent to the end user, however if you wanted to make this a bit more pre-processed, you could do all the calculation within an interpolation block:

{
/* Show parts of the calculation (current) */
margin-inline-start: calc(#{$switch-width} - #{$switch-height} / 2 - var(#{$css-var-prefix}border-width) * 3);
/* Evaluated: */
margin-inline-start: calc(2.25em - 1.25em / 2 - var(--pico-border-width) * 3);

/* Interpolate everything (alternate) */
margin-inline-start: calc(#{$switch-width - $switch-height * 0.5} - var(#{$css-var-prefix}border-width) * 3);
/* Evaluated: */
margin-inline-start: calc(1.625em - var(--pico-border-width) * 3);
}

If you're planning to make the switch sizes variables for users to scale horizontally or vertically, this would probably be worse.