You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

仅用CSS能否实现获焦按钮再次点击后失焦?Styled Components场景

用Styled Components实现点击切换按钮颜色(无需JavaScript)

你当前的代码用:focus伪类实现了获焦时变蓝,但再次点击按钮并不会让它失焦,所以没法切回红色。要实现点击切换状态的效果,CSS本身没有直接对应伪类,我们可以借助表单元素的checked状态来完成,下面是具体实现方案:

方案:借助隐藏的Checkbox实现切换

利用checkbox的选中/未选中状态,配合CSS兄弟选择器来控制按钮样式,完全不需要JavaScript逻辑:

import styled from "styled-components";

const ToggleWrapper = styled.div`
  position: relative;

  /* 隐藏原生checkbox */
  input[type="checkbox"] {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
  }

  /* 把label样式改成按钮的样子 */
  label {
    display: inline-block;
    width: 200px;
    height: 100px;
    background-color: red;
    border: none;
    cursor: pointer;
    color: #fff;
    font-size: 18px;
    line-height: 100px;
    text-align: center;
    user-select: none;
  }

  /* 当checkbox被选中时,改变label的背景色 */
  input[type="checkbox"]:checked + label {
    background-color: blue;
  }
`;

export default function ToggleButton() {
  return (
    <ToggleWrapper>
      <input type="checkbox" id="color-toggle" />
      <label htmlFor="color-toggle">Button</label>
    </ToggleWrapper>
  );
}

原理说明

  1. 用label模拟按钮,label可关联checkbox,点击label会自动切换checkbox的选中状态
  2. 隐藏原生checkbox,仅展示样式化后的label
  3. 通过CSS兄弟选择器input:checked + label,在checkbox选中时修改label的背景色,实现点击切换红色/蓝色的效果

可选方案(不推荐):保留

如果一定要用原生<button>标签,可通过tabindex和:focus-within配合,但此方案无法实现"再次点击恢复红色"的需求(需点击页面其他区域才会失焦),示例如下:

import styled from "styled-components";

const ButtonWrapper = styled.div`
  button {
    width: 200px;
    height: 100px;
    background-color: red;
    border: none;
    cursor: pointer;
    color: #fff;
    font-size: 18px;
  }

  &:focus-within button {
    background-color: blue;
  }
`;

export default function ToggleButton() {
  return (
    <ButtonWrapper tabIndex="0">
      <button>Button</button>
    </ButtonWrapper>
  );
}

内容的提问来源于stack exchange,提问作者NewJr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 16:32:52