Ionic 3 to Ionic 4 SCSS migration - ionic-framework

Lately I am trying to migrate my Ionic 3 project to Ionic 4. Most of the migration is going successful but I keep having problems with my styling.
After some reading I changed a few things to my styling, listed below:
Moved global styling from app.scss to global.scss
Changed theme styling $colors for example to :root { ion-color- ... }
Changed naming of (some) components (ion-navbar to ion-toolbar, button to ion-button, etc.)
Removed page selectors in page-specific styling (so removed page-login { ... } in login.scss)
Though the styling is still not quite right. I am probably still missing some things.
As example I am using my page-specific style for my login page.
In Ionic 3 the style file looked as follows for this page:
page-login {
.content {
background: url('../assets/img/background.png') no-repeat;
background-size: cover;
#logo {
padding-top: 5rem;
}
form {
position: absolute;
bottom: 0;
width: 100%;
.logo-row {
margin-bottom: 40%;
}
.form-inputs {
.label-ios {
width: 60px;
max-width: 60px;
}
ion-icon, .select-ios, ::-webkit-input-placeholder {
color: color($colors, lightGray);
max-width: 100%;
}
.item-ios {
background: transparent;
padding-left: 0;
&:first-child {
border-top: none;
}
.input-wrapper {
padding-left: 50px;
input.text-input.text-input-ios {
color: color($colors, lightGray);
}
}
}
[icon-only] ion-icon {
line-height: 1;
}
}
}
}
}
In my Ionic 4 app I changed it to the following:
ion-content {
--background: url('../../../assets/img/background.png') no-repeat;
--background-size: cover;
#logo {
padding-top: 5rem;
}
ion-form {
--position: absolute;
--bottom: 0;
--width: 100%;
.logo-row {
margin-bottom: 40%;
}
ion-inputs {
.ios ion-label {
--width: 60px;
--max-width: 60px;
}
ion-icon, .select-ios, ::-webkit-input-placeholder {
--color: var(--ion-color-lightGray); //color($colors, lightGray);
--max-width: 100%;
}
.ios ion-item {
--background: transparent;
--padding-left: 0;
&:first-child {
--border-top: none;
}
.input-wrapper {
--padding-left: 50px;
input.text-input.text-input-ios {
--color: var(--ion-color-lightGray); //color($colors, lightGray);
}
}
}
[icon-only] ion-icon {
--line-height: 1;
}
}
}
}
There are a few things which are not styled correctly:
I thought I had to replace the most Ion specific components with ion- in front of it, for content this seems to work but the form targeting this does not seem to work (ion-form), while form (liek it used to be) also doesn't work. Any clues with what I should replace this? Or should I omit the form targeting and just keep it in ion-content?
There is also some html inline styling going on, I don't know if all these styles are still correctly used in Ionic 4? For example, I have read somewhere that I should replace padding text-center with class="ion-padding ion-text-center" but what about the inline col-x and offset-x styles?
My Ionic html login page looks as following:
<ion-header [ngClass]="'no-shadow'">
<ion-toolbar transparent>
<ion-buttons start>
<button ion-button icon-only menuToggle>
<ion-icon name="menu"></ion-icon>
</button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-row class="logo-row" *ngIf="isKeyboardHidden">
<ion-col col-8 offset-2 class="ion-padding ion-text-center">
<img id="logo" src="assets/img/logo-dia-positive.png">
</ion-col>
</ion-row>
<form #f="ngForm" (ngSubmit)="onSubmit()">
<ion-row>
<ion-col>
<p style="height: 16px"></p>
</ion-col>
</ion-row>
<ion-list no-lines class="form-inputs">
<ion-item>
<ion-label icon-only>
<ion-icon name="person"></ion-icon>
</ion-label>
<ion-input
type="text"
name="username"
[(ngModel)]="account.username"
[placeholder]="'USERNAME' | translate"
required></ion-input>
</ion-item>
<ion-item>
<ion-label icon-only>
<ion-icon name="unlock"></ion-icon>
</ion-label>
<ion-input
type="password"
name="password"
[(ngModel)]="account.password"
[placeholder]="'PASSWORD' | translate"
required></ion-input>
</ion-item>
</ion-list>
<ion-row>
<ion-col col-10 offset-1>
<ion-button
block
[disabled]="!f.valid || isLoading">
{{'LOGIN' | translate}}
</ion-button>
</ion-col>
</ion-row>
</form>
</ion-content>
<ion-footer *ngIf="isKeyboardHidden">
<ion-row>
<ion-col class="ion-text-center">
<p class="light-gray">
{{'DEVELOPED_BY' | translate}}
<span class="bold">
<a class="default-text"
href="https://www.my-company.com/"
target="_blank">
My Company
</a>
</span>
</p>
</ion-col>
</ion-row>
</ion-footer>
Any ideas or pointers what I am (still) missing?

Here you can find official migration guide. They have listed all controls which they updated and Breaking changes:
https://github.com/ionic-team/ionic/blob/master/angular/BREAKING.md#breaking-changes

Related

Image grid layout with web component images

My goal is to achieve this layout for an array of Images:
As you can see, a simple 2 column grid of square images - this is quite easy in a Bootstrap environment where one specifies 2 cols or size 6 each, then simply setting the images' CSS object-fit to cover in order to avoid stretching and setting the height to auto.
Problem is, where I'm trying to achieve this is in Ionic 4 where the img element is a web component and only certain properties are exposed to that can be customized. So far I can get the images displayed in a 2 column fashion but the aspect ratios are off.(Also I HAVE to use the element, so cannot simply use HTML5 img element).
Here is what I have so far:
<ion-grid>
<ion-row>
<ion-col size="6" *ngFor="let image of selectedImageURIs">
<ion-img [src]="image"></ion-img>
</ion-col>
</ion-row>
</ion-grid>
Note: The Ionic Framework has it's own 'Bootstrap' like framework called ion-grid. What I end up with is this:
I know need to get them to be the same in height and with and set the object fit to cover, but how can I do this with an ion-img? I is a web component so the Shadow Dom comes into play. The docs just mention "The component uses Intersection Observer internally". Will that be able to do what I need? I'm new to web components to trying to understand what I'm missing.
Here is a solution that I used for my Ionic 4 app. I used css to accomplish the look you're going for. Your template will look something like this and using ion-img to take advantage of the lazy loading feature.
html
<ion-grid>
<ion-row>
<ion-col *ngFor="let category of categories" size="6">
<button #categoryButton type="button" (click)="selectCategory(categoryButton, category)" class="category-button">
<ion-card padding class="category-card">
<ion-card-content class="category-card-content">
<ion-img *ngIf="!imageNotLoaded; else loadingCategory" src="{{category.icon_image}}" class="category-icon" (ionError)="imageNotLoaded = true"></ion-img>
<ng-template #loadingCategory>
<ion-skeleton-text animated style="height: 70px;width: 70px"></ion-skeleton-text>
</ng-template>
</ion-card-content>
<ion-card-title class="category-title">{{category.name}}</ion-card-title>
</ion-card>
</button>
</ion-col>
</ion-row>
</ion-grid>
Set up your sass code like this.
scss
ion-col {
text-align: center;
}
.active {
.category-card {
border-color: var(--ion-color-primary)!important;
box-shadow: 0 4px 16px var(--ion-color-primary)!important;
}
}
.category-button {
padding: 4px;
background: transparent;
.category-card {
min-width: 100%;
margin: 0;
border: 2px solid;
.category-card-content {
text-align: center;
.category-icon {
width: available;
}
}
.category-title {
font-size: x-small;
font-weight: bolder;
}
}
}
This then yields the final result as this picture below.
Note: this is all component level code other wise you'll need to use ::ng-deep to get around the shadow dom for your css code.
page.html
<ion-row class="row-card">
<ion-col size="6" class="col-card">
<ion-card class="card-service">
<img src="../../assets/images/services/w-medical.png" class="img-service" />
</ion-card>
</ion-col>
<ion-col size="6" class="col-card">
<ion-card class="card-service">
<img src="../../assets/images/services/w-professional.png" class="img-service" />
</ion-card>
</ion-col>
</ion-row>
page.css
.row-card{
padding: 0px 5px 0px 5px;
.col-card{
padding: 0px;
.card-service{
margin: 5px;
height: 160px;
border-radius: 0px;
padding: 8px;
box-shadow: 0px 0px;
.img-service{
height: 100%;
width: 100%;
object-fit: cover;
margin: 0 auto;
border: 0 solid #024f9a;
background: linear-gradient(#0486ca,#024f9a);
border-radius: 50%;
padding: 15px;
font-weight: bold;
}
}
}
}
Here is working one
ion-grid >
<ion-row>
<ion-col col-6 col-md-4 col-xl-3 *ngFor="let image of [1,2,3,4,5,6,7,8,9,10,11]">
<img src=''/>
<!-- <div class="image-container" [style.background-image]="'url(assets/img/' + image + '.jpg)'"></div> -->
</ion-col>
</ion-row>
</ion-grid>

Ionic 4 custom styling Shadow DOM

Been trying to change footer background but I cant get it right. I have a color for each tag but only the last tag is changed (blue - #0000ff) . How does one do styling in Ionic 4?
<template>
<ion-footer>
<ion-toolbar>
<ion-title v-if="loggedIn">
<a href="https://www.facebook.com/" target="_blank">
<ion-icon name="logo-facebook"></ion-icon>
</a>
<a href="https://www.instagram.com/" target="_blank">
<ion-icon name="logo-instagram"></ion-icon>
</a>
</ion-title>
</ion-toolbar>
</ion-footer>
</template>
<script>
export default {
name: "pageFooter",
computed: {
loggedIn() {
return this.$store.getters.loggedIn;
}
}
};
</script>
<style lang="scss">
ion-footer {
background-color: #ff0000;
ion-toolbar {
background-color: #00FF00;
ion-title {
background-color: #0000ff;
a {
font-size: 25px;
color: #000;
}
}
}
}
</style>
It has something to do with "shadow dom" concept which I dont fully undersrtand yet . This DOM structure for the footer.
Ionic 4 uses web components, so the way to style components in Ionic 4 is to use the CSS variables that Ionic provides.
In your case, set the --background property of the component:
ion-footer {
--background: #ff0000;
}

Delete Label underline

So my problem is that under my label i have an underline that i want to delete. i added no-lines to my ion-label but it's seems to not working.
Is there a way to delete it ?
<ion-item class="checkbox" >
<ion-label></ion-label>
<ion-checkbox class="checkbox-square" (ionChange)="changeEvent($event)"></ion-checkbox>
</ion-item>
And this is the css
.checkbox{
font-size: 1.03rem;
color: $blue-love;
max-width: 400px;
margin: auto;
}
Add this to your css
.checkbox .item-inner {
border-bottom: none !important;
}
Without touching the CSS: This worked out for me
https://www.codegrepper.com/code-examples/html/how+to+remove+the+underline+from+ion+item
TLDR;
<ion-item lines="none">
<ion-tags...>
</ion-item>
Add custom class inside ion-label element:
<ion-label class="custom-label-style">
Label content
</ion-label>
Then style it with text-decoration property:
.custom-label-style {
text-decoration: none;
};

How can I resize the length of an card in ionic?

Well, I want to standardize the width equal to the above, but I'm not getting any way ... I've tried margin's, width and others, but none if you want to change the size of the card. I want to leave default, do you recommend me some command or am I doing wrong? all the css commands I did was in home.scss, thank you all.
Watch the print of my app here
page-home {
.bg{
background: linear-gradient(to bottom, #00A399 0%, #fafafa 400%);
}
.bg-ions{
background:#000;
opacity:0.2;
}
.btn{
background:#000;
opacity:0.2;
color:white;
}
ion-input{
color:#FAFAFA;
}
ion-textarea{
color:#FAFAFA;
}
ion-card{
display: flex;
flex-direction: column;
width: 100%;
}
ion-card-content{
margin-left:-2%;
}
ion-item{
width:50%;
}
.summ{
color:#000;
}
::placeholder {
color: white;
opacity: 1; /* Firefox */
}
:-ms-input-placeholder { /* Internet Explorer 10-11 */
color: white;
}
::-ms-input-placeholder { /* Microsoft Edge */
color: white;
}
}
<br>
<ion-header>
<ion-navbar>
<ion-title>
HybridSumm
</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding class="bg">
<ion-item class="bg-ions">
<ion-label class="div-pai" color="primary" stacked>Title</ion-label>
<ion-input placeholder="Ex: The Bio-informatics" style="color:white;"></ion-input>
</ion-item>
<br>
<ion-item class="bg-ions">
<ion-label color="primary" stacked >Text</ion-label>
<ion-textarea placeholder="Place the text that you want to summarize." ngDefaultControl [(ngModel)]="test"></ion-textarea>
</ion-item>
<br>
<button ion-button outline style="background: white">Summarize</button>
<button ion-button>Test</button>
<br><br>
<ion-card>
<ion-card-header>
Card Header
</ion-card-header>
<ion-card-content>
{{test}}
</ion-card-content>
</ion-card>
</ion-content>
Ionic set some properties by default, and the only way to override them, is by giving them the !important rule.
It is maybe not the best practice, but it works, and ionic gives us not very much sass variables to overwrite some things.
It works for me adding this in the following SCSS rules in your code:
ion-card{
display: flex;
flex-direction: column;
width: 100% !important;
margin: 0 !important;
}
I hope it works for you.

Vertical alignment for ion-badge

I have this ion-item in my Ionic 3 application. It includes an ion-badge and an ion-button. I want them both to be vertically aligned inside the ion-item. I tried the answers in here, but it didn't work. At the end I need to have these ion-badge and ion-button side by side.
<ion-item>
<ion-badge>150</ion-badge>
<button ion-button>My Button</button>
</ion-item>
Add a class to your ion-item.
HTML:
<ion-item class="my-item">
<ion-badge>150</ion-badge>
<button ion-button>My Button</button>
</ion-item>
And add the following CSS-styles to the ion-label child of your ion-item.
SCSS:
.my-item {
ion-label {
display: flex;
flex-direction: row;
align-items: baseline
}
}
Result:
UPDATE:
Code and result with icon added to the button:
HTML:
<ion-item class="my-item">
<ion-badge>150</ion-badge>
<button ion-button icon-end>My Button
<ion-icon name="arrow-down"></ion-icon>
</button>
</ion-item>
SCSS:
.my-item {
ion-label {
display: flex;
flex-direction: row;
align-items: baseline
}
ion-icon {
margin-left: 5px;
}
}
Also i added a CSS-rule for the <ion-icon> to get som space between the text and the icon in the button.
Result:
Add vertical-align to the styling:
<ion-badge style="vertical-align: bottom;">150</ion-badge>
justify-content: center; will be work!!
ion-badge {justify-content: center; }