diff --git a/BREAKING.md b/BREAKING.md
index 64b7c7c18df..3575a2a4387 100644
--- a/BREAKING.md
+++ b/BREAKING.md
@@ -18,6 +18,7 @@ This is a comprehensive list of the breaking changes introduced in the major ver
- [Button](#version-9x-button)
- [Card](#version-9x-card)
- [Chip](#version-9x-chip)
+ - [Grid](#version-9x-grid)
Components
@@ -32,3 +33,105 @@ This is a comprehensive list of the breaking changes introduced in the major ver
Chip
- The `border-radius` of the `ios` and `md` chip now defaults to `10px` and `8px`, respectively, instead of `16px` in accordance with the iOS and Material Design 3 guidelines. To revert to the previous appearance, set the `shape` to `"round"`, or override the `--border-radius` CSS variable to specify a different value.
+
+
Grid
+
+- The properties `pull` and `push` have been deprecated and no longer work. A similar look can be achieved with the newly added property `order`.
+
+
+To reorder two columns where column 1 has `size="9" push="3"` and column 2 has `size="3" pull="9"`:
+
+**Version up to 8.x**
+```html
+
+
+ 1
+ 2
+
+
+```
+**Version 9.x+**
+```html
+
+
+ 1
+ 2
+
+
+```
+
Example 3: Push
+```html
+
+
+
+
ion-col push 1
+
+
+
ion-col push 1
+
+
+
+```
+**Version 9.x+**
+```html
+
+
+
+
ion-col size="auto" offset="1"
+
+
+
ion-col size="auto"
+
+
+
+```
+
+
Example 4: Push and Pull
+```html
+
+
+
+
ion-col size="3" size-md="6" push="9" push-md="6"
+
+
+
ion-col size="9" size-md="6" pull="3" pull-md="6"
+
+
+
+```
+**Version 9.x+**
+```html
+
+
+
+
ion-col size="auto" order="2" order-md="2"
+
+
+
ion-col size="auto" order="1" order-md="1"
+
+
+
+```
\ No newline at end of file
diff --git a/core/api.txt b/core/api.txt
index 797ca6306ed..e4597ef5934 100644
--- a/core/api.txt
+++ b/core/api.txt
@@ -622,6 +622,12 @@ ion-col,prop,offsetMd,string | undefined,undefined,false,false
ion-col,prop,offsetSm,string | undefined,undefined,false,false
ion-col,prop,offsetXl,string | undefined,undefined,false,false
ion-col,prop,offsetXs,string | undefined,undefined,false,false
+ion-col,prop,order,string | undefined,undefined,false,false
+ion-col,prop,orderLg,string | undefined,undefined,false,false
+ion-col,prop,orderMd,string | undefined,undefined,false,false
+ion-col,prop,orderSm,string | undefined,undefined,false,false
+ion-col,prop,orderXl,string | undefined,undefined,false,false
+ion-col,prop,orderXs,string | undefined,undefined,false,false
ion-col,prop,pull,string | undefined,undefined,false,false
ion-col,prop,pullLg,string | undefined,undefined,false,false
ion-col,prop,pullMd,string | undefined,undefined,false,false
@@ -641,6 +647,7 @@ ion-col,prop,sizeSm,string | undefined,undefined,false,false
ion-col,prop,sizeXl,string | undefined,undefined,false,false
ion-col,prop,sizeXs,string | undefined,undefined,false,false
ion-col,prop,theme,"ios" | "md" | "ionic",undefined,false,false
+ion-col,css-prop,--col-unit-size
ion-col,css-prop,--ion-grid-column-padding
ion-col,css-prop,--ion-grid-column-padding-lg
ion-col,css-prop,--ion-grid-column-padding-md
@@ -2006,6 +2013,7 @@ ion-router-outlet,prop,theme,"ios" | "md" | "ionic",undefined,false,false
ion-row,shadow
ion-row,prop,mode,"ios" | "md",undefined,false,false
ion-row,prop,theme,"ios" | "md" | "ionic",undefined,false,false
+ion-row,css-prop,--ion-grid-gap
ion-searchbar,scoped
ion-searchbar,prop,animated,boolean,false,false,false
diff --git a/core/src/components.d.ts b/core/src/components.d.ts
index 9be0e80d5aa..5d39ba36505 100644
--- a/core/src/components.d.ts
+++ b/core/src/components.d.ts
@@ -927,52 +927,88 @@ export namespace Components {
* The amount to offset the column for xs screens, in terms of how many columns it should shift to the end of the total available.
*/
"offsetXs"?: string;
+ /**
+ * The order of the column, in terms of where the column should position itself in the columns renderer. If no value is passed, the column order implicit value will be the order in the html structure.
+ */
+ "order"?: string;
+ /**
+ * The order of the column for lg screens, in terms of where the column should position itself in the columns renderer. If no value is passed, the column order implicit value will be the order in the html structure.
+ */
+ "orderLg"?: string;
+ /**
+ * The order of the column for md screens, in terms of where the column should position itself in the columns renderer. If no value is passed, the column order implicit value will be the order in the html structure.
+ */
+ "orderMd"?: string;
+ /**
+ * The order of the column for sm screens, in terms of where the column should position itself in the columns renderer. If no value is passed, the column order implicit value will be the order in the html structure.
+ */
+ "orderSm"?: string;
+ /**
+ * The order of the column for xl screens, in terms of where the column should position itself in the columns renderer. If no value is passed, the column order implicit value will be the order in the html structure.
+ */
+ "orderXl"?: string;
+ /**
+ * The order of the column for xs screens, in terms of where the column should position itself in the columns renderer. If no value is passed, the column order implicit value will be the order in the html structure.
+ */
+ "orderXs"?: string;
/**
* The amount to pull the column, in terms of how many columns it should shift to the start of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pull"?: string;
/**
* The amount to pull the column for lg screens, in terms of how many columns it should shift to the start of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pullLg"?: string;
/**
* The amount to pull the column for md screens, in terms of how many columns it should shift to the start of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pullMd"?: string;
/**
* The amount to pull the column for sm screens, in terms of how many columns it should shift to the start of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pullSm"?: string;
/**
* The amount to pull the column for xl screens, in terms of how many columns it should shift to the start of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pullXl"?: string;
/**
* The amount to pull the column for xs screens, in terms of how many columns it should shift to the start of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pullXs"?: string;
/**
* The amount to push the column, in terms of how many columns it should shift to the end of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"push"?: string;
/**
* The amount to push the column for lg screens, in terms of how many columns it should shift to the end of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pushLg"?: string;
/**
* The amount to push the column for md screens, in terms of how many columns it should shift to the end of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pushMd"?: string;
/**
* The amount to push the column for sm screens, in terms of how many columns it should shift to the end of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pushSm"?: string;
/**
* The amount to push the column for xl screens, in terms of how many columns it should shift to the end of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pushXl"?: string;
/**
* The amount to push the column for xs screens, in terms of how many columns it should shift to the end of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pushXs"?: string;
/**
@@ -6861,52 +6897,88 @@ declare namespace LocalJSX {
* The amount to offset the column for xs screens, in terms of how many columns it should shift to the end of the total available.
*/
"offsetXs"?: string;
+ /**
+ * The order of the column, in terms of where the column should position itself in the columns renderer. If no value is passed, the column order implicit value will be the order in the html structure.
+ */
+ "order"?: string;
+ /**
+ * The order of the column for lg screens, in terms of where the column should position itself in the columns renderer. If no value is passed, the column order implicit value will be the order in the html structure.
+ */
+ "orderLg"?: string;
+ /**
+ * The order of the column for md screens, in terms of where the column should position itself in the columns renderer. If no value is passed, the column order implicit value will be the order in the html structure.
+ */
+ "orderMd"?: string;
+ /**
+ * The order of the column for sm screens, in terms of where the column should position itself in the columns renderer. If no value is passed, the column order implicit value will be the order in the html structure.
+ */
+ "orderSm"?: string;
+ /**
+ * The order of the column for xl screens, in terms of where the column should position itself in the columns renderer. If no value is passed, the column order implicit value will be the order in the html structure.
+ */
+ "orderXl"?: string;
+ /**
+ * The order of the column for xs screens, in terms of where the column should position itself in the columns renderer. If no value is passed, the column order implicit value will be the order in the html structure.
+ */
+ "orderXs"?: string;
/**
* The amount to pull the column, in terms of how many columns it should shift to the start of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pull"?: string;
/**
* The amount to pull the column for lg screens, in terms of how many columns it should shift to the start of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pullLg"?: string;
/**
* The amount to pull the column for md screens, in terms of how many columns it should shift to the start of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pullMd"?: string;
/**
* The amount to pull the column for sm screens, in terms of how many columns it should shift to the start of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pullSm"?: string;
/**
* The amount to pull the column for xl screens, in terms of how many columns it should shift to the start of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pullXl"?: string;
/**
* The amount to pull the column for xs screens, in terms of how many columns it should shift to the start of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pullXs"?: string;
/**
* The amount to push the column, in terms of how many columns it should shift to the end of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"push"?: string;
/**
* The amount to push the column for lg screens, in terms of how many columns it should shift to the end of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pushLg"?: string;
/**
* The amount to push the column for md screens, in terms of how many columns it should shift to the end of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pushMd"?: string;
/**
* The amount to push the column for sm screens, in terms of how many columns it should shift to the end of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pushSm"?: string;
/**
* The amount to push the column for xl screens, in terms of how many columns it should shift to the end of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pushXl"?: string;
/**
* The amount to push the column for xs screens, in terms of how many columns it should shift to the end of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
"pushXs"?: string;
/**
diff --git a/core/src/components/col/col.scss b/core/src/components/col/col.scss
index ee7045e623c..d1841262e0c 100644
--- a/core/src/components/col/col.scss
+++ b/core/src/components/col/col.scss
@@ -4,6 +4,13 @@
// --------------------------------------------------
:host {
+ /**
+ * @prop --col-unit-size: The size of each Column unit.
+ */
+ --col-unit-size: calc(
+ (100% - (var(--ion-grid-columns, 12) - 1) * var(--ion-grid-gap, 0px)) / var(--ion-grid-columns, 12)
+ );
+
/**
* @prop --ion-grid-columns: The number of total Columns in the Grid
* @prop --ion-grid-column-padding: Padding for the Column
@@ -20,10 +27,55 @@
position: relative;
- flex-basis: 0;
- flex-grow: 1;
+ flex: 1;
- width: 100%;
- max-width: 100%;
min-height: 1px; // Prevent columns from collapsing when empty
+
+ overflow: auto;
+}
+
+:host(.ion-grid-col-auto) {
+ flex: 0 0 auto;
+}
+
+:host([class^="ion-grid-col--"]),
+:host([class*=" ion-grid-col--"]) {
+ flex: 0 0
+ calc(var(--ion-grid-col-span) * var(--col-unit-size) + (var(--ion-grid-col-span) - 1) * var(--ion-grid-gap, 0px));
+
+ max-width: calc(
+ var(--ion-grid-col-span) * var(--col-unit-size) + (var(--ion-grid-col-span) - 1) * var(--ion-grid-gap, 0px)
+ );
+}
+
+:host([class^="ion-grid-offset-col--"]),
+:host([class*=" ion-grid-offset-col--"]) {
+ --margin-calc: calc(
+ var(--col-unit-size) * var(--ion-grid-col-margin) + (var(--ion-grid-gap, 0px) * var(--ion-grid-col-margin))
+ );
+
+ @include margin-horizontal(var(--margin-calc), 0);
+}
+
+/*
+ * While the number of columns can be customized, we generate
+ * a default set of classes for 12 columns. In the future, this
+ * will be configurable at build time as Ionic becomes more modular.
+ * For now, 12 columns is a practical default. Developers who need
+ * more columns can override or extend these styles as needed.
+ */
+$grid-col-number: 12;
+
+@for $i from 1 through $grid-col-number {
+ :host(.ion-grid-col--#{$i}) {
+ --ion-grid-col-span: #{$i};
+ }
+
+ :host(.ion-grid-order-col--#{$i}) {
+ order: #{$i};
+ }
+
+ :host(.ion-grid-offset-col--#{$i}) {
+ --ion-grid-col-margin: #{$i};
+ }
}
diff --git a/core/src/components/col/col.tsx b/core/src/components/col/col.tsx
index 7ae3f4d9bb0..ed6fba852a1 100644
--- a/core/src/components/col/col.tsx
+++ b/core/src/components/col/col.tsx
@@ -1,12 +1,11 @@
import type { ComponentInterface } from '@stencil/core';
-import { Component, Host, Listen, Prop, forceUpdate, h } from '@stencil/core';
+import { Component, Element, Host, Listen, Prop, forceUpdate, h } from '@stencil/core';
+import { printIonWarning } from '@utils/logging';
import { matchBreakpoint } from '@utils/media';
import { getIonTheme } from '../../global/ionic-global';
-const win = typeof (window as any) !== 'undefined' ? (window as any) : undefined;
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain
-const SUPPORTS_VARS = win && !!(win.CSS && win.CSS.supports && win.CSS.supports('--a: 0'));
const BREAKPOINTS = ['', 'xs', 'sm', 'md', 'lg', 'xl'];
/**
@@ -19,6 +18,7 @@ const BREAKPOINTS = ['', 'xs', 'sm', 'md', 'lg', 'xl'];
shadow: true,
})
export class Col implements ComponentInterface {
+ @Element() el!: HTMLIonColElement;
/**
* The amount to offset the column, in terms of how many columns it should shift to the end
* of the total available.
@@ -55,71 +55,112 @@ export class Col implements ComponentInterface {
*/
@Prop() offsetXl?: string;
+ /**
+ * The order of the column, in terms of where the column should position itself in the columns renderer.
+ * If no value is passed, the column order implicit value will be the order in the html structure.
+ */
+ @Prop() order?: string;
+
+ /**
+ * The order of the column for xs screens, in terms of where the column should position itself in the columns renderer.
+ * If no value is passed, the column order implicit value will be the order in the html structure.
+ */
+ @Prop() orderXs?: string;
+
+ /**
+ * The order of the column for sm screens, in terms of where the column should position itself in the columns renderer.
+ * If no value is passed, the column order implicit value will be the order in the html structure.
+ */
+ @Prop() orderSm?: string;
+
+ /**
+ * The order of the column for md screens, in terms of where the column should position itself in the columns renderer.
+ * If no value is passed, the column order implicit value will be the order in the html structure.
+ */
+ @Prop() orderMd?: string;
+
+ /**
+ * The order of the column for lg screens, in terms of where the column should position itself in the columns renderer.
+ * If no value is passed, the column order implicit value will be the order in the html structure.
+ */
+ @Prop() orderLg?: string;
+
+ /**
+ * The order of the column for xl screens, in terms of where the column should position itself in the columns renderer.
+ * If no value is passed, the column order implicit value will be the order in the html structure.
+ */
+ @Prop() orderXl?: string;
+
/**
* The amount to pull the column, in terms of how many columns it should shift to the start of
* the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
@Prop() pull?: string;
-
/**
* The amount to pull the column for xs screens, in terms of how many columns it should shift
* to the start of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
@Prop() pullXs?: string;
/**
* The amount to pull the column for sm screens, in terms of how many columns it should shift
* to the start of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
@Prop() pullSm?: string;
/**
* The amount to pull the column for md screens, in terms of how many columns it should shift
* to the start of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
@Prop() pullMd?: string;
/**
* The amount to pull the column for lg screens, in terms of how many columns it should shift
* to the start of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
@Prop() pullLg?: string;
/**
* The amount to pull the column for xl screens, in terms of how many columns it should shift
* to the start of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
@Prop() pullXl?: string;
-
/**
* The amount to push the column, in terms of how many columns it should shift to the end
* of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
@Prop() push?: string;
-
/**
* The amount to push the column for xs screens, in terms of how many columns it should shift
* to the end of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
@Prop() pushXs?: string;
-
/**
* The amount to push the column for sm screens, in terms of how many columns it should shift
* to the end of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
@Prop() pushSm?: string;
-
/**
* The amount to push the column for md screens, in terms of how many columns it should shift
* to the end of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
@Prop() pushMd?: string;
-
/**
* The amount to push the column for lg screens, in terms of how many columns it should shift
* to the end of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
@Prop() pushLg?: string;
-
/**
* The amount to push the column for xl screens, in terms of how many columns it should shift
* to the end of the total available.
+ * @deprecated Use the combination of `size` and `order` properties to achieve the same effect.
*/
@Prop() pushXl?: string;
@@ -186,84 +227,78 @@ export class Col implements ComponentInterface {
return matched;
}
- private calculateSize() {
- const columns = this.getColumns('size');
+ private getStyleClass(property: string, className: string, acceptsAuto = false): string | undefined {
+ const colPropertyValue = this.getColumns(property);
// If size wasn't set for any breakpoint
// or if the user set the size without a value
// it means we need to stick with the default and return
// e.g.
- if (!columns || columns === '') {
+ if (!colPropertyValue || colPropertyValue === '') {
return;
}
- // If the size is set to auto then don't calculate a size
- const colSize =
- columns === 'auto'
- ? 'auto'
- : // If CSS supports variables we should use the grid columns var
- SUPPORTS_VARS
- ? `calc(calc(${columns} / var(--ion-grid-columns, 12)) * 100%)`
- : // Convert the columns to a percentage by dividing by the total number
- // of columns (12) and then multiplying by 100
- (columns / 12) * 100 + '%';
-
- return {
- flex: `0 0 ${colSize}`,
- width: `${colSize}`,
- 'max-width': `${colSize}`,
- };
- }
+ if (acceptsAuto && colPropertyValue === 'auto') {
+ return 'ion-grid-col-auto';
+ }
- // Called by push, pull, and offset since they use the same calculations
- private calculatePosition(property: string, modifier: string) {
- const columns = this.getColumns(property);
+ const valueNumber = parseInt(colPropertyValue);
- if (!columns) {
+ if (isNaN(valueNumber)) {
return;
}
- // If the number of columns passed are greater than 0 and less than
- // 12 we can position the column, else default to auto
- const amount = SUPPORTS_VARS
- ? // If CSS supports variables we should use the grid columns var
- `calc(calc(${columns} / var(--ion-grid-columns, 12)) * 100%)`
- : // Convert the columns to a percentage by dividing by the total number
- // of columns (12) and then multiplying by 100
- columns > 0 && columns < 12
- ? (columns / 12) * 100 + '%'
- : 'auto';
-
- return {
- [modifier]: amount,
- };
+ return `${className}-col--${valueNumber}`;
+ }
+
+ private getSizeClass(): string | undefined {
+ return this.getStyleClass('size', 'ion-grid', true);
}
- private calculateOffset(isRTL: boolean) {
- return this.calculatePosition('offset', isRTL ? 'margin-right' : 'margin-left');
+ private getOrderClass(): string | undefined {
+ return this.getStyleClass('order', 'ion-grid-order');
}
- private calculatePull(isRTL: boolean) {
- return this.calculatePosition('pull', isRTL ? 'left' : 'right');
+ private getOffsetClass(): string | undefined {
+ return this.getStyleClass('offset', 'ion-grid-offset');
}
- private calculatePush(isRTL: boolean) {
- return this.calculatePosition('push', isRTL ? 'right' : 'left');
+ componentDidLoad() {
+ if (
+ this.pull ||
+ this.pullLg ||
+ this.pullMd ||
+ this.pullSm ||
+ this.pullXl ||
+ this.pullXs ||
+ this.push ||
+ this.pushLg ||
+ this.pushMd ||
+ this.pushSm ||
+ this.pushXl ||
+ this.pushXs
+ ) {
+ printIonWarning(
+ '[ion-col] - The pull and push properties are deprecated and no longer work, in favor of the order and size properties.',
+ this.el
+ );
+ }
}
render() {
- const isRTL = document.dir === 'rtl';
const theme = getIonTheme(this);
+
+ const colSize = this.getSizeClass();
+ const colOrder = this.getOrderClass();
+ const colOffset = this.getOffsetClass();
+
return (
diff --git a/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-ltr-Mobile-Chrome-linux.png b/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-ltr-Mobile-Chrome-linux.png
index 89a73029ff2..a1861221446 100644
Binary files a/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-ltr-Mobile-Firefox-linux.png b/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-ltr-Mobile-Firefox-linux.png
index 7cac4c5982d..8c1b5d84f49 100644
Binary files a/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-ltr-Mobile-Firefox-linux.png and b/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-ltr-Mobile-Safari-linux.png b/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-ltr-Mobile-Safari-linux.png
index ad109d5af37..8130e862723 100644
Binary files a/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-ltr-Mobile-Safari-linux.png and b/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-rtl-Mobile-Chrome-linux.png b/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-rtl-Mobile-Chrome-linux.png
index e10497b480d..9c8c39fefc6 100644
Binary files a/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-rtl-Mobile-Chrome-linux.png and b/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-rtl-Mobile-Firefox-linux.png b/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-rtl-Mobile-Firefox-linux.png
index bbbb81fc5c9..673cf5e73da 100644
Binary files a/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-rtl-Mobile-Firefox-linux.png and b/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-rtl-Mobile-Safari-linux.png b/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-rtl-Mobile-Safari-linux.png
index fe490fa34a4..a84bf220d6c 100644
Binary files a/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-rtl-Mobile-Safari-linux.png and b/core/src/components/grid/test/basic/grid.e2e.ts-snapshots/grid-basic-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/grid/test/basic/index.html b/core/src/components/grid/test/basic/index.html
index 68b729e1794..c351e8840d7 100644
--- a/core/src/components/grid/test/basic/index.html
+++ b/core/src/components/grid/test/basic/index.html
@@ -211,6 +211,7 @@
.grid-demo ion-col div {
background-color: #f7f7f7;
border: 1px solid #ddd;
+ font-size: 0.8em;
padding: 10px 5px;
}
diff --git a/core/src/components/grid/test/offsets-pull-push/grid.e2e.ts b/core/src/components/grid/test/offsets-pull-push/grid.e2e.ts
new file mode 100644
index 00000000000..b4a22e9c1ab
--- /dev/null
+++ b/core/src/components/grid/test/offsets-pull-push/grid.e2e.ts
@@ -0,0 +1,17 @@
+import { expect } from '@playwright/test';
+import { configs, test } from '@utils/test/playwright';
+
+/**
+ * ion-grid does not have different styling per-mode
+ */
+configs({ modes: ['md'] }).forEach(({ title, screenshot, config }) => {
+ test.describe(title('grid: offsets'), () => {
+ test('should not have visual regressions', async ({ page }) => {
+ await page.goto(`/src/components/grid/test/offsets-pull-push`, config);
+
+ await page.setIonViewport();
+
+ await expect(page).toHaveScreenshot(screenshot(`grid-offsets`));
+ });
+ });
+});
diff --git a/core/src/components/grid/test/offsets-pull-push/grid.e2e.ts-snapshots/grid-offsets-md-ltr-Mobile-Chrome-linux.png b/core/src/components/grid/test/offsets-pull-push/grid.e2e.ts-snapshots/grid-offsets-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..c0014a677a3
Binary files /dev/null and b/core/src/components/grid/test/offsets-pull-push/grid.e2e.ts-snapshots/grid-offsets-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/grid/test/offsets-pull-push/grid.e2e.ts-snapshots/grid-offsets-md-ltr-Mobile-Firefox-linux.png b/core/src/components/grid/test/offsets-pull-push/grid.e2e.ts-snapshots/grid-offsets-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 00000000000..bbc2aac6fa6
Binary files /dev/null and b/core/src/components/grid/test/offsets-pull-push/grid.e2e.ts-snapshots/grid-offsets-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/grid/test/offsets-pull-push/grid.e2e.ts-snapshots/grid-offsets-md-ltr-Mobile-Safari-linux.png b/core/src/components/grid/test/offsets-pull-push/grid.e2e.ts-snapshots/grid-offsets-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 00000000000..cd5d74ffd51
Binary files /dev/null and b/core/src/components/grid/test/offsets-pull-push/grid.e2e.ts-snapshots/grid-offsets-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/grid/test/offsets-pull-push/grid.e2e.ts-snapshots/grid-offsets-md-rtl-Mobile-Chrome-linux.png b/core/src/components/grid/test/offsets-pull-push/grid.e2e.ts-snapshots/grid-offsets-md-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..f8e1183c35d
Binary files /dev/null and b/core/src/components/grid/test/offsets-pull-push/grid.e2e.ts-snapshots/grid-offsets-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/grid/test/offsets-pull-push/grid.e2e.ts-snapshots/grid-offsets-md-rtl-Mobile-Firefox-linux.png b/core/src/components/grid/test/offsets-pull-push/grid.e2e.ts-snapshots/grid-offsets-md-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 00000000000..07f94379599
Binary files /dev/null and b/core/src/components/grid/test/offsets-pull-push/grid.e2e.ts-snapshots/grid-offsets-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/grid/test/offsets-pull-push/grid.e2e.ts-snapshots/grid-offsets-md-rtl-Mobile-Safari-linux.png b/core/src/components/grid/test/offsets-pull-push/grid.e2e.ts-snapshots/grid-offsets-md-rtl-Mobile-Safari-linux.png
new file mode 100644
index 00000000000..489163c9fb4
Binary files /dev/null and b/core/src/components/grid/test/offsets-pull-push/grid.e2e.ts-snapshots/grid-offsets-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/grid/test/offsets-pull-push/index.html b/core/src/components/grid/test/offsets-pull-push/index.html
new file mode 100644
index 00000000000..4117f49d4ae
--- /dev/null
+++ b/core/src/components/grid/test/offsets-pull-push/index.html
@@ -0,0 +1,107 @@
+
+
+
+
+ Grid - Pull & Push
+
+
+
+
+
+
+
+
+
+
+
+
+ Grid - Offsets
+
+
+
+
+
Push
+
+
+
+
ion-col push 1
+
+
+
ion-col push 1
+
+
+
+
+
Push and Pull
+
+
+
+
ion-col push 3
+
+
+
ion-col pull 9
+
+
+
+
+
+
+
+
ion-col size="3" size-md="6" push="9" push-md="6"
+
+
+
ion-col size="9" size-md="6" pull="3" pull-md="6"
+
+
+
+
+
Offset
+
+
+
+
ion-col offset=5
+
+
+
ion-col offset="2"
+
+
+
+
+
Dynamic Offset
+
+
+
+
ion-col offset="2" offset-md="5"
+
+
+
ion-col offset="2" offset-md="5"
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-ltr-Mobile-Chrome-linux.png b/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-ltr-Mobile-Chrome-linux.png
index 496d883050b..12d8d575122 100644
Binary files a/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-ltr-Mobile-Firefox-linux.png b/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-ltr-Mobile-Firefox-linux.png
index e02bce540e3..d4e6e57c6f4 100644
Binary files a/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-ltr-Mobile-Firefox-linux.png and b/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-ltr-Mobile-Safari-linux.png b/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-ltr-Mobile-Safari-linux.png
index 9e318858249..91d99ffdb0e 100644
Binary files a/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-ltr-Mobile-Safari-linux.png and b/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-rtl-Mobile-Chrome-linux.png b/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-rtl-Mobile-Chrome-linux.png
index e65ffeec4e6..0df61acca65 100644
Binary files a/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-rtl-Mobile-Chrome-linux.png and b/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-rtl-Mobile-Firefox-linux.png b/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-rtl-Mobile-Firefox-linux.png
index a33bb5e235a..77d81d121ca 100644
Binary files a/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-rtl-Mobile-Firefox-linux.png and b/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-rtl-Mobile-Safari-linux.png b/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-rtl-Mobile-Safari-linux.png
index 0c4c506f839..65f73fda12b 100644
Binary files a/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-rtl-Mobile-Safari-linux.png and b/core/src/components/grid/test/offsets/grid.e2e.ts-snapshots/grid-offsets-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/grid/test/offsets/index.html b/core/src/components/grid/test/offsets/index.html
index 09318a2ce96..eebd67a699f 100644
--- a/core/src/components/grid/test/offsets/index.html
+++ b/core/src/components/grid/test/offsets/index.html
@@ -23,37 +23,37 @@
-