htmlcssfluent-design

CSS-only and layout friendly Reveal Focus from Fluent Design System


In the Reveal focus docs its:

enter image description here

But, as the docs

Reveal focus increases the size of the focus visual, which might cause issues with your UI layout. In some cases, you'll want to customize the Reveal focus effect to optimize it for your app.

How would you approach creating the effect that does not affect the UI in the way described above?

My Reveal focus component:

  1. Reveal glow is box-shadow
  2. Primary focus visual is outline
  3. Secondary focus visual is border
  4. Background

but something seems off and I can't quite grasp it. Is it box-shadow, is it spacing (like margin, I don't set any as you can see), or is it yet something else? How would you fix it if you wanted it to look like on the gif below?

body {
  background-color: #000;
  padding: 5px 100px;
}
.tile {
  display: inline-block;
  height: 82px;
  background-color: #555555;
}
.x1 { width: 19%; }
.x2 { width: 38%; }

.reveal-focus {
  border: 1px solid transparent;
  outline: 2px solid transparent;
}

.reveal-focus:focus {
  outline-color: #61B250;
  box-shadow: 0 0 15px 3px #61B250;
}
<a href="#" class="tile reveal-focus x1"></a>
<a href="#" class="tile reveal-focus x1"></a>
<a href="#" class="tile reveal-focus x1"></a>
<a href="#" class="tile reveal-focus x2"></a>
<a href="#" class="tile reveal-focus x2"></a>
<a href="#" class="tile reveal-focus x1"></a>
<a href="#" class="tile reveal-focus x1"></a>
<a href="#" class="tile reveal-focus x1"></a>

enter image description here


Solution

  • The shadow is being placed above elements that appear before the focused one, but below elements after it. You need to add position: relative to all the elements, and z-index: 1 to the focused one.

    To make sure this doesn't interfere with any other stacking, apply position: relative; z-index: 0 to the container. This ensures that it has its own stacking context.

    The GIF you show appears to also have a slight animation effect, with the glow being more intense for just a moment before fading to normal. This can be achieved quite simply with animation.

    body {
      background-color: #000;
      padding: 5px 100px;
    }
    .tile {
      display: inline-block;
      height: 82px;
      background-color: #555555;
    }
    .x1 { width: 19%; }
    .x2 { width: 38%; }
    
    .reveal-focus {
      border: 1px solid transparent;
      outline: 2px solid transparent;
      position: relative;
    }
    
    .reveal-focus:focus {
      border-color: #000;
      outline-color: #61B250;
      box-shadow: 0 0 15px 3px #61B250;
      animation: glowfade 0.4s linear;
      z-index: 1;
    }
    
    @keyframes glowfade {
      from {box-shadow: 0 0 30px 6px #61B250;}
      to {box-shadow: 0 0 15px 3px #61B250;}
    }
    <a href="#" class="tile reveal-focus x1"></a>
    <a href="#" class="tile reveal-focus x1"></a>
    <a href="#" class="tile reveal-focus x1"></a>
    <a href="#" class="tile reveal-focus x2"></a>
    <a href="#" class="tile reveal-focus x2"></a>
    <a href="#" class="tile reveal-focus x1"></a>
    <a href="#" class="tile reveal-focus x1"></a>
    <a href="#" class="tile reveal-focus x1"></a>

    Adjust values as desired.