skip to Main Content

When I focus this control it gets an outline, as desired, but when I click with the primary mouse button and hold then the outline disappears whilst I hold it. How can I fix it?

:root {
  --color-mint: #02b689;
  --color-white: #ffffff;
  --color-silver: #c2c2c2;
  --focus-color: #3b3e3f;
  --focus-opacity: 0.5;
}

.toggle {
  position: relative;
  display: inline-block;
  width: 60px;
  height: 26px;
}

.toggle input {
  width: 0;
  height: 16px;
  pointer-events: none;
}

.toggle_slider {
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: var(--color-silver);
  transition: .3s;
  border-radius: 26px;
}

.toggle_slider:before {
  position: absolute;
  content: "";
  height: 22px;
  width: 22px;
  left: 2px;
  bottom: 2px;
  background-color: var(--color-white);
  transition: .3s;
  border-radius: 50%;
}

.toggle_slider::after {
  content: "";
  border-radius: 26px;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  border: 2px solid var(--focus-color);
  margin: -3px;
  opacity: 0;
}

input:checked+.toggle_slider {
  background-color: var(--color-mint);
}

input:checked+.toggle_slider:before {
  transform: translateX(34px);
}

.toggle input:focus+.toggle_slider::after {
  opacity: var(--focus-opacity);
}
<label class="toggle">
    <input type=checkbox aria-hidden="true" />
    <span class="toggle_slider round"></span>
</label>

Note: I don’t want to resort to JavaScript if possible.

2

Answers


  1. The issue you’re experiencing is due to the default behavior of some browsers to remove the outline when an element is clicked or receives focus. This behavior is often associated with the CSS :focus pseudo-class.

    To prevent the outline from disappearing when you click and hold the element, you can modify the :focus style to explicitly define the outline for the focused state.

    .toggle {
      position: relative;
      display: inline-block;
      width: 60px;
      height: 26px;
    }
    
    .toggle input {
      width: 0;
      height: 16px;
      pointer-events: none;
    }
    
    .toggle_slider {
      position: absolute;
      cursor: pointer;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background-color: var(--color-silver);
      transition: .3s;
      border-radius: 26px;
    }
    
    /* Add the following style to explicitly define the outline for the :focus state */
    .toggle input:focus + .toggle_slider {
      outline: 2px solid var(--focus-color);
      outline-offset: -1px;
    }
    

    With this modification, when the checkbox inside the .toggle element receives focus (e.g., when it is clicked), the .toggle_slider will have a 2px solid outline with the –focus-color specified in your :root block. The outline-offset is used to make the outline surround the element without affecting its size.

    Now, when you click and hold the element, the outline will remain visible.

    Login or Signup to reply.
  2. It is fixed. Now if you click the button and hold then the outline will not disappear. Sorry, I couldn’t find a way to do it with CSS.

    document.querySelector('.toggle').addEventListener('mousedown', function(){
        document.styleSheets[0].cssRules[5].style.opacity = "var(--focus-opacity)";
        /*Currently, it is targeting the selector ".toggle_slider::after"
          So, Remember to change the styleSheets[0] and cssRules[5] values according to your stylesheet number and rule number.*/
    })
    
    document.querySelector('.toggle').addEventListener('mouseup', function(){
        document.styleSheets[0].cssRules[5].style.opacity = "0";
    }) 
    :root {
    --color-mint: #02b689;
    --color-white: #ffffff;
    --color-silver: #c2c2c2;
    --focus-color: #3b3e3f;
    --focus-opacity: 0.5;
    }
    
    .toggle {
    position: relative;
    display: inline-block;
    width: 60px;
    height: 26px;
    }
    
    .toggle input {
    width: 0;
    height: 16px;
    pointer-events: none;
    }
    
    .toggle_slider {
    position: absolute;
    cursor: pointer;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: var(--color-silver);
    transition: .3s;
    border-radius: 26px;
    }
    
    .toggle_slider:before {
    position: absolute;
    content: "";
    height: 22px;
    width: 22px;
    left: 2px;
    bottom: 2px;
    background-color: var(--color-white);
    transition: .3s;
    border-radius: 50%;
    }
    
    .toggle_slider::after {
    content: "";
    border-radius: 26px;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    border: 2px solid var(--focus-color);
    margin: -3px;
    opacity: 0;
    }
    
    input:checked+.toggle_slider {
    background-color: var(--color-mint);
    }
    
    input:checked+.toggle_slider:before {
    transform: translateX(34px);
    }
    
    .toggle input:focus+.toggle_slider::after {
    opacity: var(--focus-opacity);
    }
    <label class="toggle">
        <input type=checkbox aria-hidden="true"/>
        <span class="toggle_slider round"></span>
    </label>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search