Stop Yahoo! Mail from Rendering Your Media Queries


UPDATE: As of March 2015, Yahoo! Mail has remedied this issue with media query rendering. Read more at Yahoo! Mail Now Supports Media Queries.

In April 2011, Campaign Monitor published this article which identifies an issue in the way Yahoo! Mail handles media queries. With the help of Brian Sisolak @bsisolak at Trilogy Interactive, we’ve identified a few more issues with regard to the way Yahoo! Mail handles media query styles intended for mobile devices only. To make a long story short, each version of Yahoo! ignores your media query declaration along with all of its conditional statements. It then renders each of the styles as if they are outside of the media query to begin with. On top of that, it gets confused with your first declaration which is therefore ignored. So for example, this:

<style>
 @media only screen and (max-device-width: 480px) {
   #smallScreen {width:100px; padding:2px;}
   .desktop {width:500px; padding:10px;}
 }
</style>

Will get converted to this:

<style>
 _filtered #yiv1449593645 {padding:2px;} 
 #yiv1449593645 .yiv1449593645desktop {width:500px;padding:10px;} 
 #yiv1449593645
</style>

As you can see, Yahoo! converts each of your style names into a name that is unique to your email. They do this in order to keep your styles separate from the ones they use in their interface. So later in the document, it also converts your HTML:

<div class="desktop">Text</div>

Is converted to:

<div class=" yiv1449593645desktop ">Text</div>

Although Yahoo! has really good intentions, I think the problem is occurring because their parsing tool does not take into account media queries and the way they are formatted.

So what’s the fix?

Campaign Monitor came up with a sneaky solution to use attribute selectors since they are not supported either.  That way your media query and the styles within will not get picked up by Yahoo!

To give an example, if I convert my original query from above, it would look like this:

<style>
 @media only screen and (max-device-width: 480px) {
   *[id=smallScreen] {width:100px; padding:2px;}
   *[class=desktop] {width:500px; padding:10px;}
 }
</style>

Another option is to use attribute selectors a little differently wherein you add a “*[class]” before all class declarations and “*[id]” before ID’s like this:

<style>
 @media only screen and (max-device-width: 480px) {
   *[id]#smallScreen {width:100px; padding:2px;}
   *[class].desktop {width:500px; padding:10px;}
 }
</style>

The bugger about using the examples above is that each element controlled within your media query must contain an HTML attribute (id, class, style, etc). Unfortunatly, universal, type and decendent selectors are out of the question.

So here’s one more creative tactic that gives you access to additional selector types:

<style>
   @media only screen and (max-device-width: 480px) {
      body[yahoo] p {color:#00C}
      body[yahoo] .foo {color:#C03}
      body[yahoo] .bar {color:#C03}
    }
 </style>
...
<body yahoo="fix">
    <p>test</p>
   <p class="foo">test</p>
   <div class="bar">test</div>
</body>

In this example, I am making up a “yahoo” attribute and placing it in the body tag.  I could have left out the value “fix” but this will help me remember what it’s for later on.  Then I am placing “body[yahoo] ” before each declaration which now allows me to access universal selectors.

Each of the recommendations above will work in both Yahoo! Classic and Yahoo! Mail.