Home > OS >  SVG mask translation lags on Chromium browsers
SVG mask translation lags on Chromium browsers

Time:03-19

I am the author of a collection of animated SVG theme-toggles. I have noticed that any which involve translating a mask are extremely choppy on chromium browsers but are fine on Firefox.

The toggles in question are Classic and Expand

The animations are seemingly throttled possibly due to Chromium thinking the masks is out of view. Whilst the issue seems to persist for the majority of the time, there are a few occasions where they do work on Chromium, I have no explanation as to why they sometimes work.

Any help in solving this issue would be greatly appreciated. I have found a similar issue with Firefox described here but haven't fully figured out the cause of worked out a solution.

.theme-toggle {
  font-size: 10rem;
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/css/classic.min.css" rel="stylesheet"/>
<label >
  <input type="checkbox" />
  <span >Toggle theme</span>
  <svg
    xmlns="http://www.w3.org/2000/svg"
    width="1em"
    height="1em"
    fill="currentColor"
    stroke-linecap="round"
    
    viewBox="0 0 32 32"
  >
    <mask id="theme-toggle__classic__cutout" color="#000">
      <path fill="#fff" d="M0 0h32v32H0z" />
      <circle cx="34" cy="2" r="8" />
    </mask>
    <circle
      cx="16"
      cy="16"
      r="9.34"
      mask="url(#theme-toggle__classic__cutout)"
    />
    <g
      stroke="currentColor"
      
      mask="url(#theme-toggle__classic__cutout)"
    >
      <path d="M16 5.5v-4" />
      <path d="M16 30.5v-4" />
      <path d="M1.5 16h4" />
      <path d="M26.5 16h4" />
      <path d="m23.4 8.6 2.8-2.8" />
      <path d="m5.7 26.3 2.9-2.9" />
      <path d="m5.8 5.8 2.8 2.8" />
      <path d="m23.4 23.4 2.9 2.9" />
    </g>
  </svg>
</label>

CodePudding user response:

This seems at least to improve performance in Chromium. I have made three changes:

  1. exchange the mask for a clip-path
  2. apply the clip-path only once to a parent group encompassing both the circle and the rays
  3. This one made the difference: do not transition the transform, but the d path data directly. For both Chrome (99) and Firefox (98) you can now write the CSS syntax d: path('...') and animate the path data. I currently can't test with Safari.

.theme-toggle.theme-toggle--reversed .theme-toggle__classic {
    transform: scale(-1,1)
}

.theme-toggle {
    --theme-toggle__classic--duration: 750ms
}

.theme-toggle__classic * {
    transition-property: opacity,transform,d;
    transition-timing-function: cubic-bezier(0,0,0.15,1.25);
    transform-origin: center;
    transition-duration: var(--theme-toggle__classic--duration);
    transition-delay: calc(var(--theme-toggle__classic--duration) / 5);
}

.theme-toggle__classic #theme-toggle__classic__cutout path {
    transition-delay: 0s;
    d: path('M0-10h34v4a8 8 0 108 8h1v32h-43z');
}

.theme-toggle input[type=checkbox]:checked~.theme-toggle__classic .theme-toggle__classic__sun-rays *,
.theme-toggle--toggled:not(label).theme-toggle .theme-toggle__classic .theme-toggle__classic__sun-rays * {
    transform: scale(.5) rotate(45deg);
    opacity: 0;
    transition-delay: 0s
}

.theme-toggle input[type=checkbox]:checked~.theme-toggle__classic #theme-toggle__classic__cutout path,
.theme-toggle--toggled:not(label).theme-toggle .theme-toggle__classic #theme-toggle__classic__cutout path {
    d: path('M-11 0h34v4a8 8 0 108 8h1v32h-43z');
    transition-delay: calc(var(--theme-toggle__classic--duration) / 5)
}

button.theme-toggle,label.theme-toggle {
    border: none;
    background: 0 0;
    cursor: pointer
}

button.theme-toggle input[type=checkbox],label.theme-toggle input[type=checkbox] {
    display: none
}

button.theme-toggle .theme-toggle-sr,label.theme-toggle .theme-toggle-sr {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0,0,0,0);
    white-space: nowrap;
    border-width: 0
}

.theme-toggle {
  font-size: 10rem;
}
<label >
  <input type="checkbox" />
  <span >Toggle theme</span>
  <svg
    xmlns="http://www.w3.org/2000/svg"
    width="1em"
    height="1em"
    fill="currentColor"
    stroke-linecap="round"
    
    viewBox="0 0 32 32"
  >
    <clipPath id="theme-toggle__classic__cutout">
      <path />
    </clipPath>
    <g clip-path="url(#theme-toggle__classic__cutout)">
      <circle cx="16" cy="16" r="9.34" />
      <g
        stroke="currentColor"
        
      >
        <path d="M16 5.5v-4" />
        <path d="M16 30.5v-4" />
        <path d="M1.5 16h4" />
        <path d="M26.5 16h4" />
        <path d="m23.4 8.6 2.8-2.8" />
        <path d="m5.7 26.3 2.9-2.9" />
        <path d="m5.8 5.8 2.8 2.8" />
        <path d="m23.4 23.4 2.9 2.9" />
      </g>
    </g>
  </svg>
</label>

  • Related