diff --git a/spec/amp-html-layout.md b/spec/amp-html-layout.md index 2366fbce4280..25ef70efc5da 100644 --- a/spec/amp-html-layout.md +++ b/spec/amp-html-layout.md @@ -160,6 +160,26 @@ In the following example, if the viewport is wider than `320px`, the image will ``` +### `disable-inline-width` + +The `sizes` attribute on its own will set an inline `width` style on the element. When pairing `disable-inline-width` with `sizes`, the AMP element will propagate the value of `sizes` to the element's underlying tag, as with the `img` nested inside an `amp-img`, **without** setting the inline `width` as `sizes` typically does on its own in AMP. + +**Example**: Using the `disable-inline-width` attribute + +In the following example, the width of the `` element is unaffected, and `sizes` is only used to select one of the sources from the `srcset`. + +```html + + +``` + ### `heights` All AMP elements that support the `responsive` layout, also support the `heights` attribute. diff --git a/src/custom-element.js b/src/custom-element.js index 549f05c49f2e..bb271f71b4c9 100644 --- a/src/custom-element.js +++ b/src/custom-element.js @@ -697,7 +697,9 @@ function createBaseCustomElementClass(win) { // Sizes. if (this.sizeList_ === undefined) { const sizesAttr = this.getAttribute('sizes'); - this.sizeList_ = sizesAttr ? parseSizeList(sizesAttr) : null; + const isDisabled = this.hasAttribute('disable-inline-width'); + this.sizeList_ = + !isDisabled && sizesAttr ? parseSizeList(sizesAttr) : null; } if (this.sizeList_) { setStyle( diff --git a/test/unit/test-amp-img.js b/test/unit/test-amp-img.js index b89fd87f6697..0ad6ad442d4e 100644 --- a/test/unit/test-amp-img.js +++ b/test/unit/test-amp-img.js @@ -205,6 +205,22 @@ describes.sandboxed('amp-img', {}, env => { }); }); + it('should propagate srcset and sizes with disable-inline-width', async () => { + const ampImg = await getImg({ + src: '/examples/img/sample.jpg', + srcset: SRCSET_STRING, + sizes: '(max-width: 320px) 640px, 100vw', + width: 320, + height: 240, + 'disable-inline-width': null, + }); + const img = ampImg.querySelector('img'); + expect(img.getAttribute('srcset')).to.equal(SRCSET_STRING); + expect(img.getAttribute('sizes')).to.equal( + '(max-width: 320px) 640px, 100vw' + ); + }); + describe('#fallback on initial load', () => { let el; let impl; diff --git a/test/unit/test-custom-element.js b/test/unit/test-custom-element.js index 102473953356..0a57095a946f 100644 --- a/test/unit/test-custom-element.js +++ b/test/unit/test-custom-element.js @@ -1164,6 +1164,13 @@ describes.realWin('CustomElement', {amp: true}, env => { element2.ampdoc_ = env.ampdoc; }); + it('should not apply sizes when "disable-inline-width" is present', () => { + element1.setAttribute('disable-inline-width', null); + element1.setAttribute('sizes', '(min-width: 1px) 200px, 50vw'); + element1.applySizesAndMediaQuery(); + expect(element1.style.width).not.to.equal('200px'); + }); + it('should apply media condition', () => { element1.setAttribute('media', '(min-width: 1px)'); element1.applySizesAndMediaQuery(); diff --git a/validator/validator-main.protoascii b/validator/validator-main.protoascii index ee197e27a5e4..33e723bf6d6c 100644 --- a/validator/validator-main.protoascii +++ b/validator/validator-main.protoascii @@ -5439,6 +5439,7 @@ tags: { # their values. attr_lists: { name: "$AMP_LAYOUT_ATTRS" + attrs: { name: "disable-inline-width" } attrs: { name: "height" } attrs: { name: "heights" } attrs: { name: "layout" }