<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Aleksandra Lando</title>
    <description>The latest articles on DEV Community by Aleksandra Lando (@aleksandra_lando_).</description>
    <link>https://dev.to/aleksandra_lando_</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3386085%2F45448c64-2b03-46f3-9ef2-eb505fe8dad1.jpg</url>
      <title>DEV Community: Aleksandra Lando</title>
      <link>https://dev.to/aleksandra_lando_</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aleksandra_lando_"/>
    <language>en</language>
    <item>
      <title>Fixing Blurry Text When Stopping CSS Transform Animations (The Data Attribute Hack)</title>
      <dc:creator>Aleksandra Lando</dc:creator>
      <pubDate>Thu, 24 Jul 2025 21:04:19 +0000</pubDate>
      <link>https://dev.to/aleksandra_lando_/fixing-blurry-text-when-stopping-css-transform-animations-the-data-attribute-hack-50a5</link>
      <guid>https://dev.to/aleksandra_lando_/fixing-blurry-text-when-stopping-css-transform-animations-the-data-attribute-hack-50a5</guid>
      <description>&lt;p&gt;Have you ever tried stopping a &lt;code&gt;transform: translateY()&lt;/code&gt; animation and noticed that your text or images become blurry? It happens because CSS transforms often leave elements at sub-pixel positions (e.g., &lt;code&gt;translateY(-385.562px)&lt;/code&gt;), which causes anti-aliasing issues.&lt;/p&gt;

&lt;p&gt;This is especially annoying when you're working with &lt;strong&gt;WAAPI (Web Animations API)&lt;/strong&gt; or CSS animations that loop infinitely, and you want to &lt;strong&gt;pause or stop the animation smoothly.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Well, here’s a simple hack that forces your element to “snap” to integer pixel values when you stop the animation, restoring that perfect crispness.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;CSS transform animations can leave elements at fractional pixel positions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When you stop the animation, elements may be positioned at translateY(-385.562px).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This results in blurry text, distorted borders, and a generally messy look.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simply setting .style.transform doesn’t help because the running animation overrides it.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Solution — Snap to Integer with &lt;code&gt;data-attribute&lt;/code&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Snap Current Transform to Integer (JS Function)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const snapTransformToInteger = (el) =&amp;gt; {
  const computedStyle = getComputedStyle(el);
  const match = computedStyle.transform.match(/matrix.*\((.+)\)/);

  if (match) {
    const values = match[1].split(', ');
    const translateY = parseFloat(values[5]); // matrix(a, b, c, d, tx, ty)
    const roundedY = Math.round(translateY);
    el.style.setProperty('--stopTranslateY', `${roundedY}px`);
    el.dataset.stopAnimation = 'true';
  }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Force CSS Transform with Data Attribute
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.element[data-stop-animation='true'] {
  transform: translateY(var(--stopTranslateY, 0px)) !important;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. When You Want to Stop Animation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Stop the animation smoothly and fix blurry pixels
snapTransformToInteger(el);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. When You Want to Resume
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Remove &lt;code&gt;data-stop-animation&lt;/code&gt; attribute.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Resume your WAAPI animation.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;el.dataset.stopAnimation = 'false';
// Resume the animation here.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why This Works
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;WAAPI animations or CSS animations will always win over direct .style edits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But CSS selectors like [data-stop-animation='true'] with !important can override inline transforms.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;By forcing a CSS variable-based transform, you “lock” the element in place.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once you're ready to resume, remove the attribute and resume the animation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This trick is perfect for cases when you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Need to pause infinite transform animations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Want your UI to stop without blurry elements.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hate sub-pixel rendering glitches after animations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s a small hack, but it &lt;strong&gt;saves hours of frustration&lt;/strong&gt;. And the best part? No need to rewrite your animations with absolute positioning hacks or crazy workarounds.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>css</category>
      <category>waapi</category>
      <category>animation</category>
    </item>
  </channel>
</rss>
