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" }