2

Codepen

I just created a custom selection pop-up. Now inspecting it in other browsers, I can't avoid, but notice the little offset of the white "dot", inside the radio button, Firefox renders. Chrome and Edge will display it just fine, but Firefow won't. And rather out of curiosity I'd like to know, why's that? And how to avoid?

enter image description here enter image description here


The "dot":

&::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 50%;
  height: 50%;
  border-radius: 50%;
  background-color: var(--light);
  transform: translate(-50%, -50%);
}

Entire radio button:

input[type=radio] {
  position: relative;
  height: 24px;
  width: 24px;
  margin: 0;
  border-radius: 50%;
  border: solid 1px var(--light-contrast);
  background-color: var(--light);
  appearance: none;
  cursor: pointer;
  
  &:checked {
    border-color: var(--accent);
    background-color: var(--accent);
  }
  
  &:focus {
    outline: 0;
  }
  
  &::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 50%;
    height: 50%;
    border-radius: 50%;
    background-color: var(--light);
    transform: translate(-50%, -50%);
  }
}

Whole snippet:

:root {
  --dark: #212121;
  --dark-contrast: #424242;
  --light: #fafafa;
  --light-contrast: #cfd8dc;
  --accent: #2196f3;
}

*,
::after,
::before {
  box-sizing: border-box;
}

html {
  font-family: 'Roboto', sans-serif;
  font-size: 1rem;
  line-height: 1.5;
}

body {
  display: grid;
  place-items: center;
  height: 100vh;
  margin: 0;
  background-color: var(--dark);
}

ul, li {
  margin: 0;
  padding: 0;
  list-style: none;
}

.select {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  max-width: 300px;
  background-color: var(--dark-contrast);
  color: #fff;
  box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.25);
  cursor: pointer;
  user-select: none;
  padding: 1.25rem 1.5rem;
  border-radius: 4px;
}
.select:focus {
  outline: 0;
}
.select:focus .list {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
  pointer-events: all;
}
.select:hover {
  background-color: #484848;
}
.select::after {
  display: inline-block;
  content: '';
  border-left: .3755rem solid transparent;
  border-right: .3755rem solid transparent;
  border-top: .375rem solid #fff;
}
.select .list {
  position: fixed;
  top: 50%;
  left: 50%;
  width: clamp(300px, 75vw, 320px);
  border-radius: 4px;
  background-color: var(--light);
  color: #000;
  transform: translate(-50%, -50%) scale(0);
  transition: all 400ms ease;
  opacity: 0;
  pointer-events: none;
  overflow: hidden;
}
.select .list label {
  display: flex;
  align-items: center;
  padding: 1.25rem 1.5rem;
  cursor: pointer;
}
.select .list label:hover {
  background-color: #ededed;
}
.select .list label:active {
  background-color: #e1e1e1;
  transition: 200ms ease;
}
.select .list label input[type=radio] {
  margin-right: 1rem;
}

input[type=radio] {
  position: relative;
  height: 24px;
  width: 24px;
  margin: 0;
  border-radius: 50%;
  border: solid 1px var(--light-contrast);
  background-color: var(--light);
  appearance: none;
  cursor: pointer;
}
input[type=radio]:checked {
  border-color: var(--accent);
  background-color: var(--accent);
}
input[type=radio]:focus {
  outline: 0;
}
input[type=radio]::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 50%;
  height: 50%;
  border-radius: 50%;
  background-color: var(--light);
  transform: translate(-50%, -50%);
}
<div class="select" tabindex="1">
  Select
  <div class="list">
    <label for="select-radio1">
      <input type="radio" id="select-radio1" name="select-radio">
      Chrome
    </label>
    <label for="select-radio2">
      <input type="radio" id="select-radio2" name="select-radio">
      Safari
    </label>
    <label for="select-radio3">
      <input type="radio" id="select-radio3" name="select-radio">
      Firefox
    </label>
  </div>
</div>
Simplicius
  • 2,009
  • 1
  • 5
  • 19
  • 1
    Both your snippet and the CodePen link viewed in latest Firefox appear to be perfectly aligned. Must be something else throwing the position off. By the way I only find Chrome to have a display bug when it comes to transform translate. – SJacks Sep 23 '20 at 15:18
  • 1
    It's a matter of subpixels. Your input is `24px` wide, your before `11px`, leaving `13px` to dispatch in equal parts. – Amaury Hanser Sep 23 '20 at 15:21
  • From my understanding certain styles do not work the same way on Firefox. Edge and chrome are both based on chromium so you should not see any difference. Try this piece of code and comment back here if it resolved the difference. '-moz-appearance: radio !important;' – SaaSy Monster Sep 23 '20 at 15:22
  • @AresZephyr, I explicitly set `apperance` to `none`, to use a custom styling, but thanks. – Simplicius Sep 23 '20 at 15:23
  • @AmauryHanser, so Chrome and Firefox handle subpixels differently? – Simplicius Sep 23 '20 at 15:24
  • @SJacks, Hmm, I'm on latest Firefox too, that's weird, might it be a question of the bios? Btw could you describe the visual bug? – Simplicius Sep 23 '20 at 15:25
  • 1
    @Simplicius Short answer: yes. – Amaury Hanser Sep 23 '20 at 15:30
  • 1
    @Simplicius Sure. I have an old answer to this here: https://stackoverflow.com/questions/14677490/blurry-text-after-using-css-transform-scale-in-chrome/59363865#59363865 – SJacks Sep 23 '20 at 15:36
  • 1
    @SJacks, thanks, I'll take a look into it. – Simplicius Sep 23 '20 at 15:39

1 Answers1

1

Subpixel rendering is handled differently across browsers.

As this SO-Post states:

[...] the problem arises from a different approach to subpixel calculus between browsers.

Also: there is no cross-browser solution, but only workarounds.

Simplicius
  • 2,009
  • 1
  • 5
  • 19