Search code examples
htmlcss

Is possible that a button that has focus and click again on it clear its focus, using just css?


I want to make a focused button lose its focus after being clicked again. To illustrate, I want to click at the red button and it will become blue, then click again on it and it become red again.

import styled from "styled-components";

const Button = styled.button`
    width: 200px;
    height: 100px;
    background-color: red;

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

export default function ButtonFocus() {
    return <Button>Button</Button>;
}

I know how to make it with javascript, but i'm triyng to make it using just css (styled component in that case, just to keep it on the same page).


Solution

  • i want to click at the red button and it will become blue, than click again on it and it become red again.

    Yes, you can achieve this effect.

    You'll need to include two :focus-able child elements within the <button>.

    Think about the following:

    1. If you apply the attribute tabindex="0" you can make any element :focus-able.
    2. If you apply the style pointer-events: none you can make any element unresponsive to clicks (and, thus, unable to receive focus from user-interaction)
    3. If you apply the style opacity: 0 you can render any element invisible (or completely transparent, at any rate)

    Consequently, if you give your <button> two :focusable <span> child-elements, you can, via CSS, alternate each <span> between the two following states:

    • visible (opacity: 1) but unresponsive to clicks (pointer-events: none)
    • responsive to clicks (pointer-events: auto) but invisible (opacity: 0)

    Working Example:

    button {
      position: relative;
      width: 100px;
      height: 100px;
      border: 1px solid rgb(0, 0, 0);
      cursor: pointer;
    }
    
    .layer1,
    .layer2 {
      position: absolute;
      inset: 0;
    }
    
    .layer1 {
      background-color: red;
      opacity: 1;
      pointer-events: none;
    }
    
    .layer2 {
      background-color: blue;
      opacity: 0;
      pointer-events: auto;
    }
    
    .layer1:focus,
    .layer2:focus {
      opacity: 1;
      pointer-events: none;
    }
    <button type="button">
      <span class="layer1" tabindex="0"></span>
      <span class="layer2" tabindex="0"></span>
    </button>