Flex-item in row. Flex-item elements will fill up availabe parent's space.
+
+
+
+
+
+
+
Flex-item in column. Flex-item elements will fill up availabe parent's space.
+
+
+
+
+
+
+
Set flex-item's size through flex-basis.
+
+
+
+
+
+
+
Set flex-item's size through flex-grow.
+
+
+
+
+
+
+
Non flex container parent with flex-item children.
+
+
+
+
+
+
+
Flex container parent contain both flex-item children and non flex-item children.
+
+
+
+
+
+
+
+
Flex container parent with non flex-item children. Children's width and height have to be set manually.
+
+
+
+
+
+
+
diff --git a/gulpfile.js b/gulpfile.js
index 3462b763a158..a944215b796a 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -296,6 +296,7 @@ function buildExamples(watch) {
buildExample('dailymotion.amp.html');
buildExample('carousel.amp.html');
buildExample('csp.amp.html');
+ buildExample('layout-flex-item.amp.html');
buildExample('metadata-examples/article-json-ld.amp.html');
buildExample('metadata-examples/article-microdata.amp.html');
buildExample('metadata-examples/recipe-json-ld.amp.html');
diff --git a/spec/amp-html-layout.md b/spec/amp-html-layout.md
index ff8bf547da32..3a54cd59869d 100644
--- a/spec/amp-html-layout.md
+++ b/spec/amp-html-layout.md
@@ -68,6 +68,8 @@ the layout of a `fill` element matches its parent.
The element lets its children to define its size, much like a normal HTML `div`.
+### `flex-item`
+The element and other elements in its parent with layout type `flex-item` take their parent container's remaining space when parent has `display: flex`.
## Layout Attributes
@@ -104,6 +106,7 @@ maintaining the height based on the aspect ratio.
container. Its children are rendered immediately.
- `nodisplay`: The component takes up zero space on the screen as if its display style was `none`.
The `width` and `height` attributes are not required.
+- `flex-item`: Element size will be determined by the parent element and the number of other elements inside parent according to `display:flex` CSS layout.
Each element documents which `layout` values it supported. If an element does not support the
specified value it would trigger a runtime error.
@@ -215,8 +218,8 @@ The element is sized and displayed based on the `layout`, `width`, `height` and
by the runtime. All of the layout rules are implemented via CSS internally. The element is said to
"define size" if its size is inferrable via CSS styles and does not change based on its children:
available immediately or inserted dynamically. This does not mean that this element's size cannot
-change. The layout could be fully responsive as is the case with `responsive`, `fixed-height` and
-`fill` layouts. It simply means that the size does not change without an explicit user action, e.g.
+change. The layout could be fully responsive as is the case with `responsive`, `fixed-height`, `fill` and
+`flex-item` layouts. It simply means that the size does not change without an explicit user action, e.g.
during rendering or scrolling or post download.
If the element has been configured incorrectly it will not be rendered at all in PROD and in DEV mode
@@ -242,3 +245,4 @@ apply as is the case with `amp-pixel` and `amp-audio`.
| fixed-height | `height` only. `width` can be `auto` | yes, specified by the parent container and `height` | no | `block` |
| fill | no | yes, parent's size | no | `block` |
| container | no | no | no | `block` |
+| flex-item | no | no | yes, based on parent container | `block` |
diff --git a/src/custom-element.js b/src/custom-element.js
index 629418d4def6..03741d5871a8 100644
--- a/src/custom-element.js
+++ b/src/custom-element.js
@@ -230,6 +230,15 @@ export function applyLayout_(element) {
// Do nothing. Elements themselves will check whether the supplied
// layout value is acceptable. In particular container is only OK
// sometimes.
+ } else if (layout == Layout.FLEX_ITEM) {
+ // Set height and width to a flex item if they exist.
+ // The size set to a flex item could be overridden by `display: flex` later.
+ if (width) {
+ element.style.width = width;
+ }
+ if (height) {
+ element.style.height = height;
+ }
}
return layout;
}
diff --git a/src/layout.js b/src/layout.js
index 9089691a9c4d..7c014740fe68 100644
--- a/src/layout.js
+++ b/src/layout.js
@@ -32,6 +32,7 @@ export const Layout = {
RESPONSIVE: 'responsive',
CONTAINER: 'container',
FILL: 'fill',
+ FLEX_ITEM: 'flex-item',
};
@@ -122,7 +123,8 @@ export function isLayoutSizeDefined(layout) {
return (layout == Layout.FIXED ||
layout == Layout.FIXED_HEIGHT ||
layout == Layout.RESPONSIVE ||
- layout == Layout.FILL);
+ layout == Layout.FILL ||
+ layout == Layout.FLEX_ITEM);
}
diff --git a/test/functional/test-layout.js b/test/functional/test-layout.js
index 5782b3c0fb1a..1c59e0367998 100644
--- a/test/functional/test-layout.js
+++ b/test/functional/test-layout.js
@@ -279,6 +279,18 @@ describe('Layout', () => {
expect(div.children.length).to.equal(0);
});
+ it('layout=flex-item', () => {
+ div.setAttribute('layout', 'flex-item');
+ div.setAttribute('width', 100);
+ div.setAttribute('height', 200);
+ expect(applyLayout_(div)).to.equal(Layout.FLEX_ITEM);
+ expect(div.style.width).to.equal('100px');
+ expect(div.style.height).to.equal('200px');
+ expect(div).to.have.class('-amp-layout-flex-item');
+ expect(div).to.have.class('-amp-layout-size-defined');
+ expect(div.children.length).to.equal(0);
+ });
+
it('layout=unknown', () => {
div.setAttribute('layout', 'foo');
expect(function() {