Ionic version:
[x] 4.x
Columns have padding between individual columns, however, the padding can be removed from the grid and columns by adding
no-paddingon the grid.
Source: https://ionicframework.com/docs/layout/grid
Current behavior:
Giving the ion-grid no-padding, the ion-cols still have padding.
Expected behavior:
The ion-cols should not have padding, like mentioned in the documentation and was before in ionic 3.
Steps to reproduce:
Start with the ionic blank template, go to the home.page.html template and add:
Related code:
<ion-grid no-padding>
<ion-row>
<ion-col>
Test
</ion-col>
</ion-row>
</ion-grid>
Ionic info:
Ionic:
ionic (Ionic CLI) : 4.10.2 (/usr/local/lib/node_modules/ionic)
Ionic Framework : @ionic/angular 4.0.1
@angular-devkit/build-angular : 0.12.4
@angular-devkit/schematics : 7.2.4
@angular/cli : 7.2.4
@ionic/angular-toolkit : 1.3.0
System:
NodeJS : v8.11.3 (/usr/local/bin/node)
npm : 6.7.0
OS : macOS Mojave

Hi @brandyscarney ,
Can i take this up.
@santoshyadav198613 Absolutely, thank you! 馃檪
Hi @brandyscarney ,
It works fine, tested with latest version adding one repo as well https://github.com/santoshyadav198613/Ionic-ToDoApp
Thanks for testing @santoshyadav198613! So I believe the problem reported is that the columns shouldn't have padding if no-padding is on the parent ion-grid. I was able to reproduce this in a Codepen: https://codepen.io/brandyscarney/pen/zbEqwg?editors=1100
You can see the first grid has padding on the ion-grid but it is removed in the second grid, but the column padding remains in both.
This is the relevant code: https://github.com/ionic-team/ionic/blob/master/core/src/components/grid/grid.scss#L46
Thanks for clarifying @brandyscarney will look into this again.
And thanks for pointing to the code as well.
Hi @brandyscarney ,
Did some research on this, the problem here is slotted only considers the immediate child and will ignore any child to its child element so code below code will never work
:host([no-padding]) ::slotted(ion-col) {
@include padding(0);
}
https://github.com/webcomponents/shadydom/issues/258
Found above issue on webcomponents as well, will looks for work around.
Please help with work around if any.
@santoshyadav198613
@brandyscarney
Just some brainstorming, since I am not familiar with StencilJS:
Is there something like content projection in angular, so you could check if the ion-grid has got child elements inserted (ion-row, ion-col) and you would set the padding class on these dependent on the attribute of the ion-grid component.
Now this starts go get messy, if it is nested (which it probably is) with these three components:
<ion-grid no-padding>
<ion-row>
<ion-col></ion-col>
<ion-col></ion-col>
</ion-row>
<ion-row>
<ion-col></ion-col>
<ion-col></ion-col>
</ion-row>
</ion-grid>
Because now you would probably need to pass through the information of the no-padding attribute of the ion-grid to the ion-row which would need to pass this again to his ion-col childs.
You could use some service within the scope of these three components (at least in angular for example)
Maybe it's possible to access the parent and check his attribute.
export class IonColComponent {
@HostBinding('class.no-padding')
public noPadding = false;
constructor(@Optional() private readonly ionGrid: GridComponent) {
if (ionGrid) {
this.noPadding = this.ionGrid.hasNoPaddingAttribute();
}
}
}
export class IonColComponent {
constructor(private readonly element: ElementRef) {
const componentElement = this.element.nativeElement as HTMLElement;
const nextIonGridParent: HTMLElement | null = Utils.getParentTagElementUntil(componentElement, 'ion-grid');
if (nextIonGridParent) {
const hasNoPaddingAttribute: boolean = nextIonGridParent.getAttribute('no-padding') !== null;
if (hasNoPaddingAttribute) {
componentElement.classList.add('no-padding');
}
}
}
}
export class Utils {
public static getParentTagElementUntil(element: HTMLElement, tagName: string): HTMLElement | null {
let currentElement = element.parentElement;
while (currentElement) {
if ((currentElement.tagName || '').toUpperCase().indexOf(tagName) > -1) {
return currentElement;
}
currentElement = currentElement.parentElement;
}
return null;
}
}
Same as Idea 3 above but with querySelector
Let the ion-row and ion-col have also the no-padding attribute.
Downside: In our case, we would need to set these in a lot of elements.
<ion-grid no-padding>
<ion-row no-padding>
<ion-col no-padding></ion-col>
<ion-col no-padding></ion-col>
</ion-row>
<ion-row no-padding>
<ion-col no-padding></ion-col>
<ion-col no-padding></ion-col>
</ion-row>
</ion-grid>
Make it configurable what the default padding for the ion-grid and his children (ion-row and ion-col) is.
Pro: In our case, it would be easier to set the default to 0px padding and in case we want some padding, we would just go into the HTML and set it right there, where we need it.
<ion-grid no-padding>
<ion-row>
<ion-col padding-l-xs="2"></ion-col>
<ion-col padding-r-xs="2"></ion-col>
</ion-row>
<ion-row>
<ion-col padding-h-xs="3"></ion-col>
<ion-col padding-v-xs="3"></ion-col>
</ion-row>
</ion-grid>
$grid-padding-width: 10px !default;
$screen-breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
) !default;
@each $keySize, $valueSize in $screen-breakpoints {
@media (min-width: $valueSize) {
@for $i from 0 through 28 {
$value : $i * 0.25;
// Padding
[padding-l-#{$keySize}='#{$value}'] {
padding-left: $grid-padding-width * $value !important;
}
[padding-r-#{$keySize}='#{$value}'] {
padding-right: $grid-padding-width * $value !important;
}
[padding-t-#{$keySize}='#{$value}'] {
padding-top: $grid-padding-width * $value !important;
}
[padding-b-#{$keySize}='#{$value}'] {
padding-bottom: $grid-padding-width * $value !important;
}
[padding-v-#{$keySize}='#{$value}'] {
padding-top: $grid-padding-width * $value !important;
padding-bottom: $grid-padding-width * $value !important;
}
[padding-h-#{$keySize}='#{$value}'] {
padding-left: $grid-padding-width * $value !important;
padding-right: $grid-padding-width * $value !important;
}
}
}
}
@santoshyadav198613 @brandyscarney
Guys come on?
Even a global css override would work, or not?
If not, what is the reason it cannot work? So we gather here everything and can finally come to a solution.
ion-grid[no-padding] {
& > ion-row {
padding: 0;
& > ion-col {
padding: 0;
}
}
}
Hey @StefanRein , sorry for the delay I will look into this over the weekend. And thanks for the suggestion will try that out 馃槉.
There are CSS variables that exist for overriding padding: https://ionicframework.com/docs/layout/grid#customizing-the-grid
Grid Padding:
--ion-grid-padding: 5px;
--ion-grid-padding-xs: 5px;
--ion-grid-padding-sm: 5px;
--ion-grid-padding-md: 5px;
--ion-grid-padding-lg: 5px;
--ion-grid-padding-xl: 5px;
Column Padding:
--ion-grid-column-padding: 5px;
--ion-grid-column-padding-xs: 5px;
--ion-grid-column-padding-sm: 5px;
--ion-grid-column-padding-md: 5px;
--ion-grid-column-padding-lg: 5px;
--ion-grid-column-padding-xl: 5px;
Here's a Codepen: https://codepen.io/brandyscarney/pen/MNvWwB?editors=1100
Honestly, we will likely remove the no-padding attribute entirely in the next major version. We're moving away from recommending CSS attributes because it causes conflicts / typescript errors in frameworks that use JSX. You can read more in depth on that in my comment here: https://github.com/ionic-team/ionic/pull/18374#issuecomment-495657061
Let me know if there's a reason the CSS variables don't work, thanks!
@brandyscarney
I understand that attributes could cause conflicts in certain frameworks.
To speak just for the angular framework, it was really handy to have attribute selectors with values.
For example it could be super easy to bind:
<my-component text-align="center"></..>
as
<my-component [text-align]="alignmentVariable"></..>
Still to be honest, we had in our application with ~700 components barely the need to do this.
Our application is designed for desktop and mobile and we started to use heavily your grid components for alignment since it is really handy.
So we ended up in a lot of cases having a no padding on the top grids and a padding in the inner grids.
Thank you for sharing the information, so we at least will not rely on this padding attribute to be shipped with ionic and will just provide our CSS, like mentioned above :)
@StefanRein You should still be able to add the class dynamically:
<ion-card-header [className]="someCondition ? 'ion-text-center' : null">
We could add the no padding attribute as a class that just targets CSS variables, but the problem stems from not being able to pass styles down to slotted components (ion-cols) inside of a slotted component (ion-row), which is where the CSS variables come in.
The ::slotted() CSS pseudo-element represents any element that has been placed into a slot inside an HTML template (see Using templates and slots for more information).
https://drafts.csswg.org/css-scoping/#slotted-pseudo
For a stylesheet within the shadow tree, a selector like ::slotted(*) selects #one and #two only, as they鈥檙e the elements assigned to the sole slot element. It will not select #three (no slot attribute) nor #four (only direct children of a shadow host can be assigned to a slot).
This is essentially not fixable using CSS styles alone, and will require us (or the user) to set CSS variables.
Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.