如何在大纲下隐藏 ::before 或 ::after?

How to hide a ::before or ::after under the outline?

我试过:

on chrome on firefox

我注意到只有当 'outline' 设置为 'auto' 时才会出现此问题。
有什么想法可以在不影响浏览器默认大纲的情况下修复它吗?

谢谢。

#switch {
  position: relative;
  background: transparent;
  border: 0;
  width: 30px;
  height: 30px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

#switch:focus {
  outline: 5px dotted blue;
  outline-style: auto;
  z-index: 0;
}

#switch .mode {
  position: relative;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #1a202c;
  transition: transform 0.45s ease;
}

#switch .mode::after {
  content: "";
  position: absolute;
  width: 100%;
  height: 100%;
  top: -30%;
  left: 30%;
  border-radius: 50%;
  background: white;
  transition: transform 0.45s ease;
}
<button id="switch">
    <div class="mode"></div>
  </button>

只使用背景而不是伪元素来做不同的事情。你也可以有透明度:

#switch {
  background: pink;
  border: 0;
  width: 30px;
  height: 30px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

#switch:focus {
  outline: 5px dotted blue;
  outline-style: auto;
}

#switch .mode {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: 
    radial-gradient(circle 10px,transparent 98%,#1a202c)
    bottom 20% left 20%/ /* adjust this to control the position */
    200% 200%;
  transition: transform 0.45s ease;
}
<button id="switch">
    <div class="mode"></div>
  </button>

获取有关 radial-gradient 的更多详细信息:

尝试将 overflow: hidden 添加到 #switch .mode,然后在黑暗中将其设置为 visible

const button = document.getElementById("switch");
const container = document.querySelector(".container");

window.addEventListener("load", () => {
  if (document.window.matchMedia("(prefers-color-scheme: dark)").matches) {
    container.classList.toggle("dark");
  }
});

button.addEventListener("click", () => {
  container.classList.toggle("dark");
});
*,
*::before,
*::after {
  margin: 0;
  box-sizing: border-box;
}

.container {
  margin: 0;
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  background: white;
}

#switch {
  position: relative;
  background: transparent;
  border: 0;
  width: 30px;
  height: 30px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
#switch:focus {
  outline: 5px dotted blue;
  outline-style: auto;
  z-index: 0;
}

#switch .mode {
  position: relative;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background:linear-gradient(to left bottom,white 35%,#1a202c 35%);
  transition: transform 0.45s ease;
  overflow: hidden;
}

#switch .mode::before {
  content: "";
  position: absolute;
  width: 6px;
  height: 6px;
  left: 50%;
  top: 50%;
  transform: translateX(-50%) translateY(-50%);
  border-radius: 50%;
  background: inherit;
  z-index: -1;
  opacity: 0;
  transition: box-shadow 0.4s 0s ease;
}

#switch .mode::after {
  content: "";
  position: absolute;
  width: 100%;
  height: 100%;
  top: -30%;
  left: 30%;
  border-radius: 50%;
  background: white;
  transition: transform 0.45s ease;
}

.container.dark {
  background: #1a202c;
}
.container.dark #switch .mode {
  transform: scale(0.5);
  background: white;
  overflow: visible;
}
.container.dark #switch .mode::before {
  opacity: 1;
  box-shadow: 0 -20px 0 0 white, 0 20px 0 0 white, -20px 0 0 0 white, 20px 0 0 0 white, 15px 15px 0 0 white, 15px -15px 0 0 white, -15px 15px 0 0 white, -15px -15px 0 0 white;
}
.container.dark #switch .mode::after {
  opacity: 0;
  transform: translateX(50%) translateY(-50%);
}
<div class="container dark">
  <button id="switch">
    <div class="mode"></div>
  </button>
</div><div class="container dark">
  <button id="switch">
    <div class="mode"></div>
  </button>
</div>