103

I'm experiencing an issue with the CSS transition property beeing fired on page load.

The problem is that when I apply a color transition to an element, (ex: transition: color .2s) then when the page first loads my elements flashes from black to it's own assigned color.

Supposing I have the following code:

CSS

p.green {
   color: green;
   transition: color .2s;
   -moz-transition: color .2s;
   -webkit-transition: color .2s;
   -o-transition: color .2s;
}

p.green:hover {
   color: yellow;
}

HTML

<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN'
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
    <script src="js/main.js"></script>
    <link href="css/main.css" rel="stylesheet" />
</head>
<body>
    <p class="green">The Flashing Text</p>
</body>
</html>

On page load, my p.green will fade from black to green.

I don't want to apply the color transition to the :hover pseudo class as that would not apply the transition onMouseLeave.

I'ts really annoying having the text flashing across the webpage. Up to this moment I have been avoiding using transitions unless I really need them and even so I use with care. It would be great if there is some really obvious solution to this that I'm not seeing!

This happens on Google Chrome. I haven't tested in other browsers.

jsfiddle.net/ShyZp/2 (thanks @Shmiddty)

vsync
  • 118,978
  • 58
  • 307
  • 400
nienn
  • 2,130
  • 2
  • 15
  • 21
  • 2
    Quick thought: `window.onload = function(){document.body.className += " loaded";}` `body.loaded p.green{transition:color .2s;}` – Shmiddty Jan 17 '13 at 22:53
  • 2
    That would work if you have only a small number of classes with color transition. I'm looking for a non JavaScript answer preferably... – nienn Jan 17 '13 at 22:58
  • I can't recreate the problem in Chrome: http://jsfiddle.net/ShyZp/ – Shmiddty Jan 17 '13 at 22:58
  • the problem doesn't happen for me in chrome, provide us with your exact code in a jsfiddle please... – Ilan Biala Jan 17 '13 at 23:06
  • @Shmiddty I had tryed a jsfiddle before too and could not recreate it. Not sure if it's because of the page scripts... I only see the text appearing almost at the end of the page load so maybe that ruins the effect... Ill try doing some more tests... – nienn Jan 17 '13 at 23:06
  • are the `body{color:red;}` and `p.green{color:green;}` in separate files? – Shmiddty Jan 17 '13 at 23:08
  • 1
    The problem can be seen here, but this is only valid if the two declarations aren't happening in the same file: http://jsfiddle.net/ShyZp/2/ – Shmiddty Jan 17 '13 at 23:09
  • Or, to be more specific, if `p.green` isn't defined before the elements are created. – Shmiddty Jan 17 '13 at 23:11
  • @Shmiddty yes, I have a separate css file which I call on my html file header. Thta's exacly the problem I'm having. Thanks for the working fiddle! – nienn Jan 17 '13 at 23:17
  • Can you update your question to include the basic/reduced HTML structure include which files each style is declared in, and how each stylesheet is included? – Shmiddty Jan 17 '13 at 23:25

9 Answers9

140

There is a bug in Chrome that causes CSS transitions to fire if the page includes a <form> element.

One simple fix is to add a script tag containing a single space to the footer of the page.

<script> </script>

You can follow the bug at https://crbug.com/332189 and https://crbug.com/167083.

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
spencer.sm
  • 19,173
  • 10
  • 77
  • 88
  • 4
    I had `` at the end of my document. Removing the `async` attribute fixed the unwanted transitions on page load. – Kyle Fox Sep 26 '17 at 03:11
  • 2
    Like @KyleFox I had a `defer` on my ` – jonathanbell Apr 28 '18 at 02:27
  • This worked inconsistently for me (previously the bug happened 100% of the time; with this change it happened 50% of the time). What *did* work 100% of the time, which this answer inspired me to try, was reordering stuff in the `` of my document so that my CSS was included *before* my JavaScript instead of after it; I literally solved the bug by moving my Google Analytics ` – Mark Amery Mar 31 '19 at 14:31
  • 4
    FWIW, I was still having this issue even with no JS on the page. The only thing that fixed it for me was moving the CSS to the start of the `` tag. I added `` to the `` so it would still download right away. – Ted Whitehead Jun 13 '19 at 19:34
  • I didn't have a
    element in my page and it solved the bug
    – Cesar Castro Nov 19 '20 at 12:47
  • I am not sure how this works but I added this right before my `` tag and it seems to have worked. – NoDisplayName Dec 10 '22 at 17:40
54

@Shmiddty comments on this question left me thinking, so I have been playing around with the code and found a solution.

The problem lies on the header declarations. By inverting the order of the CSS and JS external file calls - i.e. putting the CSS before the JS - the color transitions stop firing on page load:

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <link href="css/main.css" rel="stylesheet" />
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
    <script src="js/main.js"></script>
</head>

My guess is that the JS load was delaying the load of the CSS to after the DOM was ready. By that time (as @Shmiddty suggested) the text had already been assigned the default browser color and was then using my CSS transition declaration to fade into its styled color.

** I'm still not sure this is the most appropriate way to do it, but it works. If anyone has a better solution please feel free to add or edit.

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
nienn
  • 2,130
  • 2
  • 15
  • 21
18

Add to your CSS:

.css-transitions-only-after-page-load * {
  -webkit-transition: none !important;
  -moz-transition: none !important;
  -ms-transition: none !important;
  -o-transition: none !important;
  transition: none !important;
}

And add some code to your global JavaScript file:

$(document).ready(function () {
    $(".css-transitions-only-after-page-load").each(function (index, element) {
        setTimeout(function () { $(element).removeClass("css-transitions-only-after-page-load") }, 10);
    });
});

Now you can mark any element on your page with css-transitions-only-after-page-load class:

<div class="container css-transitions-only-after-page-load">
...
</div>
Utmost Creator
  • 814
  • 1
  • 9
  • 21
Roman Pushkin
  • 5,639
  • 3
  • 40
  • 58
7

nienn posts the solution. The problem lies in the document head, and where/how you are loading your stylesheets. It's similar to the "can't modify headers, they're already sent" in PHP, except HTML/CSS/webkit doesn't throw you an error.

I was experiencing this exact problem, read nienn's post, and I reviewed my head. Here were my contents previously.

<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <html lang="en">
    <meta name="description" content="A website for me to do whatever I want with." >
    <title>My title</title>
    <link rel="stylesheet" type="text/css" href="/mD/media/foot.css">
    <link rel="stylesheet" href="mD/media/head.css" type="text/css">
</head>

Notice I'm not loading any JS, also note of how I was loading the style sheets page after specifying the title. After moving the stylesheet-references to the 'back', it worked like a charm. The end result looked like this:

<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <html lang="en">
    <meta name="description" content="A website for me to do whatever I want with." >
    <link rel="stylesheet" type="text/css" href="/mD/media/foot.css">
    <link rel="stylesheet" href="mD/media/head.css" type="text/css">
    <title>My title</title>
</head>

It's not only javascript that can cause this problem, but the site title as well. I guess a good rule of thumb is css > js > site title.

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
Lando
  • 419
  • 3
  • 8
  • Just to add I had the same issue and it turned out it was a video delaying the page load. Removing the video on iOS fixed the issue. – Scott w Sep 30 '15 at 12:26
  • Can you add MDN or w3.org reference to back up your claim? This solution doesn't work in the latest browsers. – user31782 Sep 25 '21 at 11:53
6

The accepted answer did not do the trick for me. There's a bug in Google Chrome that can be avoided just by adding a script in the page. Even an empty script solves the problem.

Manuszep
  • 813
  • 11
  • 20
  • Surprised that this bug has been going on for years. Just to add to the answer, the ` – Kenny Worden Nov 15 '16 at 06:04
6

The best way to solve this problem is to use the single space, empty <script> fix found in the answers on this page. However I've found 2 other ways to solve this problem.

  1. Place the CSS of the offending element(s) inside a <style> tag in the header of your HTML file. The bug only occurs when the CSS is called from an external stylesheet.
  2. Place the offending element(s) in a flexbox container. This fixes the bug as well.
DR01D
  • 1,325
  • 15
  • 32
4

You can just add an empty script tag to your html file.

Like this:

<script type="text/javascript"></script>

but it should include at least one character. Either space or new line (\n) or comment (//) or whatever

<script type="text/javascript"> </script>

<script type="text/javascript">
</script>

<script type="text/javascript">//</script>

Or just link a js file to your html file

<script type="text/javascript" src="js/script.js"></script>

You can place the script tag everywhere you want. In the head or body tag.

This problem only happen during development because at the final situation of a website it will definitely have a js file

aria T
  • 89
  • 6
0

To fix CSS transition from firing on page load for me, the cause was Google Adsense script header, i.e.

<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=..." crossorigin></script>

The fix is to remove the async attribute

<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=..." crossorigin></script>

If you are wondering why it works, I don't know for sure.

I just think it's kinda funny how Google's script broke it's browser. It wasn't so funny trying to solve this for hours.

Polar
  • 11
  • 1
  • 2
  • 1
    This is crazy in 2023 is still an issue, I could never figure out of this if I didn't found this question! Anyway for me to work I had to add in the head not footer. – silvered.dragon Feb 08 '23 at 18:06
-3

Have you tried using different transition properties? Such as:

-moz-transition: color .2s; /* Firefox 4 */
-webkit-transition: color .2s; /* Safari and Chrome */
-o-transition: color .2s; /* Opera */

Worked just fine for me in Chrome.

EDIT: You answered the question about browsers already. You should try using -webkit-transform

Banath
  • 345
  • 3
  • 18
  • I'm using that, sorry, just thought I'd put a simplified code on the question. – nienn Jan 17 '13 at 23:01
  • Alright, by the way, I thought IE doesn't support CSS3 transitions? – Banath Jan 17 '13 at 23:18
  • Well there you go! :) You are right of course! Have been stuck on Chrome for this one, went to IE just for this question sake and didn't even thought about that *minor detail... – nienn Jan 18 '13 at 00:03