Fixing AMP Ads That Break Your Website Layout

I maintain a couple of blogs, one of which is the whiskey review site Thirty One Whiskey. That blog actually gets a good amount of traffic, and generates enough revenue from Google ads to (partially) fund my whiskey and cigar habits.

One problem that I had been running into was that the default code for Google’s AMP ads was breaking the formatting of my website on mobile devices. When rendered, the ad element was wider than the width of the page on mobile screens, so when you started to scroll, quite often the page would move to the left a bit and the text would start to be cut off.

I just fixed it with one simple change that I’m almost ashamed to say took me weeks of bashing my head against CSS code to figure out.

Here’s the default code Google gives you:

<amp-ad width="100vw" height="320"
    type="adsense"
    data-ad-client="[YOUR AD ID]"
    data-ad-slot="[YOUR ELEMENT ID]"
    data-auto-format="rspv"
    data-full-width="">
    <div overflow=""></div>
    </amp-ad>

The important bits are at the top there. Google wants you to hard set the maximum height of the element, and then allow the width of the element to be set relative to the page. It’s smart, since it allows the ad element to be responsive to the screen size.

The problem here is that the value being used is “VW” or “View Width.” That’s a relative value that is equal to the total width of the device screen. Which is fine when the element is on a flat page with no padding, but when you have padding added to the site layout the result is that your total width becomes (total width of screen) + (padding), which makes the element larger than the size of the screen.

One way to solve this is by hard setting the width of the element, but that ruins the responsive nature of the element.

I tried a number of different solutions to get it to work, but due to the AMP implementation none of them were valid. Changing that to a value less than 100 causes the element to be invalid, and trying to set it in CSS elsewhere wasn’t working for me.

But the solution was simple and staring me in the face the whole time: Change the rules of the game.

Solution

The issue is that the value being used for the element is relative to the total width of the screen. But that’s not the only relative value available in CSS. There are a bunch of other units available, which are documented on W3 here.

If you want the element to fit the container, you’re using the wrong unit. You should be using EM instead of VW.

The EM value provides the width relative to the containing element. So, in the case of this AMP ad, that would be (view width) – (left padding) – (right padding). Which is exactly what we want.

The resulting code is as follows:

<amp-ad width="100em" height="320"
    type="adsense"
    data-ad-client="[YOUR AD ID]"
    data-ad-slot="[YOUR ELEMENT ID]"
    data-auto-format="rspv"
    data-full-width="">
    <div overflow=""></div>
    </amp-ad>

This follows the rules: it’s 100% of the provided value, remains responsive, and validates as a correctly implemented chunk of AMP code.

To see it in action, walk on over to 31W and check out an article like this review of Blanton’s Bourbon.

I also added this as a solution over at Stack Overflow.