mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
feat(app): add responsive utility attributes by screen size (#11228)
- moves breakpoint mixins to the ionic.mixins file - adds responsive attributes for text alignment, transform, and floating elements - adds ability to turn these off so they don’t get added to the css file using sass variables references #10904 closes #10567
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
// Globals
|
||||
// --------------------------------------------------
|
||||
@import "../../themes/ionic.globals";
|
||||
@import "../../themes/ionic.mixins";
|
||||
|
||||
|
||||
// Normalize
|
||||
@@ -49,6 +50,36 @@ $h5-font-size: 1.8rem !default;
|
||||
$h6-font-size: 1.6rem !default;
|
||||
|
||||
|
||||
// Responsive Utilities
|
||||
// --------------------------------------------------
|
||||
|
||||
/// @prop - Whether to include all of the responsive utility attributes
|
||||
$include-responsive-utilities: true !default;
|
||||
|
||||
/// @prop - Whether to include all of the responsive text alignment attributes
|
||||
$include-text-alignment-utilities: $include-responsive-utilities !default;
|
||||
|
||||
/// @prop - Whether to include all of the responsive text transform attributes
|
||||
$include-text-transform-utilities: $include-responsive-utilities !default;
|
||||
|
||||
/// @prop - Whether to include all of the responsive float attributes
|
||||
$include-float-element-utilities: $include-responsive-utilities !default;
|
||||
|
||||
|
||||
// Screen Breakpoints
|
||||
// --------------------------------------------------
|
||||
|
||||
/// @prop - The minimum dimensions at which your layout will change,
|
||||
/// adapting to different screen sizes, for use in media queries
|
||||
$screen-breakpoints: (
|
||||
xs: 0,
|
||||
sm: 576px,
|
||||
md: 768px,
|
||||
lg: 992px,
|
||||
xl: 1200px
|
||||
) !default;
|
||||
|
||||
|
||||
// App Structure
|
||||
// --------------------------------------------------
|
||||
|
||||
@@ -293,77 +324,128 @@ ion-footer {
|
||||
// Text Alignment
|
||||
// --------------------------------------------------
|
||||
|
||||
[text-left] {
|
||||
text-align: left;
|
||||
}
|
||||
@if ($include-text-alignment-utilities == true) {
|
||||
// Creates text alignment attributes based on screen size
|
||||
@each $breakpoint in map-keys($screen-breakpoints) {
|
||||
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
|
||||
|
||||
[text-center] {
|
||||
text-align: center;
|
||||
}
|
||||
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
|
||||
// Provide `[text-{bp}]` attributes for aligning the text based
|
||||
// on the breakpoint
|
||||
[text#{$infix}-center] {
|
||||
// scss-lint:disable ImportantRule
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
[text-right] {
|
||||
text-align: right;
|
||||
}
|
||||
[text#{$infix}-justify] {
|
||||
// scss-lint:disable ImportantRule
|
||||
text-align: justify !important;
|
||||
}
|
||||
|
||||
[text-start] {
|
||||
text-align: start;
|
||||
}
|
||||
[text#{$infix}-start] {
|
||||
// scss-lint:disable ImportantRule
|
||||
text-align: start !important;
|
||||
}
|
||||
|
||||
[text-end] {
|
||||
text-align: end;
|
||||
}
|
||||
[text#{$infix}-end] {
|
||||
// scss-lint:disable ImportantRule
|
||||
text-align: end !important;
|
||||
}
|
||||
|
||||
[text-justify] {
|
||||
text-align: justify;
|
||||
}
|
||||
[text#{$infix}-left] {
|
||||
// scss-lint:disable ImportantRule
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
[text-nowrap] {
|
||||
white-space: nowrap;
|
||||
}
|
||||
[text#{$infix}-right] {
|
||||
// scss-lint:disable ImportantRule
|
||||
text-align: right !important;
|
||||
}
|
||||
|
||||
[text-wrap] {
|
||||
white-space: normal;
|
||||
[text#{$infix}-nowrap] {
|
||||
// scss-lint:disable ImportantRule
|
||||
white-space: nowrap !important;
|
||||
}
|
||||
|
||||
[text#{$infix}-wrap] {
|
||||
// scss-lint:disable ImportantRule
|
||||
white-space: normal !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Text Transformation
|
||||
// --------------------------------------------------
|
||||
|
||||
[text-uppercase] {
|
||||
text-transform: uppercase;
|
||||
@if ($include-text-transform-utilities == true) {
|
||||
// Creates text transform attributes based on screen size
|
||||
@each $breakpoint in map-keys($screen-breakpoints) {
|
||||
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
|
||||
|
||||
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
|
||||
// Provide `[text-{bp}]` attributes for transforming the text based
|
||||
// on the breakpoint
|
||||
[text#{$infix}-uppercase] {
|
||||
// scss-lint:disable ImportantRule
|
||||
text-transform: uppercase !important;
|
||||
}
|
||||
|
||||
[text#{$infix}-lowercase] {
|
||||
// scss-lint:disable ImportantRule
|
||||
text-transform: lowercase !important;
|
||||
}
|
||||
|
||||
[text#{$infix}-capitalize] {
|
||||
// scss-lint:disable ImportantRule
|
||||
text-transform: capitalize !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[text-lowercase] {
|
||||
text-transform: lowercase;
|
||||
}
|
||||
|
||||
[text-capitalize] {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
// Float
|
||||
// Float Elements
|
||||
// --------------------------------------------------
|
||||
|
||||
[pull-left] {
|
||||
float: left;
|
||||
}
|
||||
@if ($include-float-element-utilities == true) {
|
||||
// Creates text transform attributes based on screen size
|
||||
@each $breakpoint in map-keys($screen-breakpoints) {
|
||||
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
|
||||
|
||||
[pull-right] {
|
||||
float: right;
|
||||
}
|
||||
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
|
||||
// Provide `[pull-{bp}]` attributes for floating the element based
|
||||
// on the breakpoint
|
||||
[pull#{$infix}-left] {
|
||||
// scss-lint:disable ImportantRule
|
||||
float: left !important;
|
||||
}
|
||||
|
||||
[pull-start] {
|
||||
float: left;
|
||||
}
|
||||
[pull#{$infix}-right] {
|
||||
// scss-lint:disable ImportantRule
|
||||
float: right !important;
|
||||
}
|
||||
|
||||
[pull-end] {
|
||||
float: right;
|
||||
}
|
||||
[pull#{$infix}-start] {
|
||||
// scss-lint:disable ImportantRule
|
||||
float: left !important;
|
||||
}
|
||||
|
||||
[dir="rtl"] [pull-start] {
|
||||
float: right;
|
||||
}
|
||||
[pull#{$infix}-end] {
|
||||
// scss-lint:disable ImportantRule
|
||||
float: right !important;
|
||||
}
|
||||
|
||||
[dir="rtl"] [pull-end] {
|
||||
float: left;
|
||||
[dir="rtl"] [pull#{$infix}-start] {
|
||||
// scss-lint:disable ImportantRule
|
||||
float: right !important;
|
||||
}
|
||||
|
||||
[dir="rtl"] [pull#{$infix}-end] {
|
||||
// scss-lint:disable ImportantRule
|
||||
float: left !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
10
src/components/app/test/utilities/app/app.component.ts
Normal file
10
src/components/app/test/utilities/app/app.component.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import { RootPage } from '../pages/root-page/root-page';
|
||||
|
||||
@Component({
|
||||
template: `<ion-nav [root]="root"></ion-nav>`
|
||||
})
|
||||
export class AppComponent {
|
||||
root = RootPage;
|
||||
}
|
||||
22
src/components/app/test/utilities/app/app.module.ts
Normal file
22
src/components/app/test/utilities/app/app.module.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { IonicApp, IonicModule } from '../../../../..';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { RootPage } from '../pages/root-page/root-page';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
RootPage
|
||||
],
|
||||
entryComponents: [
|
||||
RootPage
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
IonicModule.forRoot(AppComponent, { statusbarPadding: true })
|
||||
],
|
||||
bootstrap: [IonicApp],
|
||||
})
|
||||
export class AppModule {}
|
||||
5
src/components/app/test/utilities/app/main.ts
Normal file
5
src/components/app/test/utilities/app/main.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
|
||||
import { AppModule } from './app.module';
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
137
src/components/app/test/utilities/pages/root-page/root-page.html
Normal file
137
src/components/app/test/utilities/pages/root-page/root-page.html
Normal file
@@ -0,0 +1,137 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Utilities</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content padding class="util-demo">
|
||||
<ion-row class="text-align-row">
|
||||
<ion-col col-4>
|
||||
<div text-center>text-center</div>
|
||||
</ion-col>
|
||||
<ion-col col-4>
|
||||
<div text-sm-center>text-sm-center</div>
|
||||
</ion-col>
|
||||
<ion-col col-4>
|
||||
<div text-md-center>text-md-center</div>
|
||||
</ion-col>
|
||||
<ion-col col-4>
|
||||
<div text-lg-center>text-lg-center</div>
|
||||
</ion-col>
|
||||
<ion-col col-4>
|
||||
<div text-xl-center>text-xl-center</div>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
|
||||
<ion-row class="text-align-row">
|
||||
<ion-col col-4>
|
||||
<div text-nowrap>text-nowrap nowrap nowrap nowrap nowrap nowrap nowrap nowrap nowrap</div>
|
||||
</ion-col>
|
||||
<ion-col col-4>
|
||||
<div text-sm-nowrap>text-sm-nowrap nowrap nowrap nowrap nowrap nowrap nowrap nowrap nowrap</div>
|
||||
</ion-col>
|
||||
<ion-col col-4>
|
||||
<div text-md-nowrap>text-md-nowrap nowrap nowrap nowrap nowrap nowrap nowrap nowrap nowrap</div>
|
||||
</ion-col>
|
||||
<ion-col col-4>
|
||||
<div text-lg-nowrap>text-lg-nowrap nowrap nowrap nowrap nowrap nowrap nowrap nowrap nowrap</div>
|
||||
</ion-col>
|
||||
<ion-col col-4>
|
||||
<div text-xl-nowrap>text-xl-nowrap nowrap nowrap nowrap nowrap nowrap nowrap nowrap nowrap</div>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
|
||||
<ion-row class="text-transform-row">
|
||||
<ion-col col-4>
|
||||
<div text-uppercase>text-uppercase</div>
|
||||
</ion-col>
|
||||
<ion-col col-4>
|
||||
<div text-sm-uppercase>text-sm-uppercase</div>
|
||||
</ion-col>
|
||||
<ion-col col-4>
|
||||
<div text-md-uppercase>text-md-uppercase</div>
|
||||
</ion-col>
|
||||
<ion-col col-4>
|
||||
<div text-lg-uppercase>text-lg-uppercase</div>
|
||||
</ion-col>
|
||||
<ion-col col-4>
|
||||
<div text-xl-uppercase>text-xl-uppercase</div>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
|
||||
<div class="float-elements-row">
|
||||
<div pull-left>pull-left</div>
|
||||
<div pull-sm-left>pull-sm-left</div>
|
||||
<div pull-md-left>pull-md-left</div>
|
||||
<div pull-lg-left>pull-lg-left</div>
|
||||
<div pull-xl-left>pull-xl-left</div>
|
||||
</div>
|
||||
|
||||
<div class="float-elements-row">
|
||||
<div pull-right>pull-right</div>
|
||||
<div pull-sm-right>pull-sm-right</div>
|
||||
<div pull-md-right>pull-md-right</div>
|
||||
<div pull-lg-right>pull-lg-right</div>
|
||||
<div pull-xl-right>pull-xl-right</div>
|
||||
</div>
|
||||
|
||||
<div class="float-elements-row">
|
||||
<div pull-start>pull-start</div>
|
||||
<div pull-sm-start>pull-sm-start</div>
|
||||
<div pull-md-start>pull-md-start</div>
|
||||
<div pull-lg-start>pull-lg-start</div>
|
||||
<div pull-xl-start>pull-xl-start</div>
|
||||
</div>
|
||||
|
||||
<div class="float-elements-row">
|
||||
<div pull-end>pull-end</div>
|
||||
<div pull-sm-end>pull-sm-end</div>
|
||||
<div pull-md-end>pull-md-end</div>
|
||||
<div pull-lg-end>pull-lg-end</div>
|
||||
<div pull-xl-end>pull-xl-end</div>
|
||||
</div>
|
||||
|
||||
<div class="float-elements-row" dir="rtl">
|
||||
<div pull-start>pull-start</div>
|
||||
<div pull-sm-start>pull-sm-start</div>
|
||||
<div pull-md-start>pull-md-start</div>
|
||||
<div pull-lg-start>pull-lg-start</div>
|
||||
<div pull-xl-start>pull-xl-start</div>
|
||||
</div>
|
||||
|
||||
<div class="float-elements-row" dir="rtl">
|
||||
<div pull-end>pull-end</div>
|
||||
<div pull-sm-end>pull-sm-end</div>
|
||||
<div pull-md-end>pull-md-end</div>
|
||||
<div pull-lg-end>pull-lg-end</div>
|
||||
<div pull-xl-end>pull-xl-end</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
|
||||
<style>
|
||||
.util-demo div {
|
||||
border: 1px solid #dedede;
|
||||
padding: 5px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.util-demo .text-transform-row div {
|
||||
background-color: lightblue;
|
||||
}
|
||||
|
||||
.util-demo .text-align-row div {
|
||||
background-color: lightpink;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.util-demo .float-elements-row {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.util-demo .float-elements-row div {
|
||||
background-color: lightyellow;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,8 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'root-page.html'
|
||||
})
|
||||
export class RootPage {
|
||||
constructor() { }
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
@import "../../themes/ionic.globals";
|
||||
@import "../../themes/ionic.mixins";
|
||||
|
||||
// Responsive Mixins
|
||||
// --------------------------------------------------
|
||||
@@ -255,52 +256,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Breakpoint Mixins
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
// Breakpoint viewport sizes and media queries.
|
||||
//
|
||||
// Breakpoints are defined as a map of (name: minimum width), order from small to large:
|
||||
//
|
||||
// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)
|
||||
//
|
||||
// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
// Minimum breakpoint width. Null for the smallest (first) breakpoint.
|
||||
//
|
||||
// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
|
||||
// 576px
|
||||
@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {
|
||||
$min: map-get($breakpoints, $name);
|
||||
@return if($min != 0, $min, null);
|
||||
}
|
||||
|
||||
|
||||
// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash infront.
|
||||
// Useful for making responsive utilities.
|
||||
//
|
||||
// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
|
||||
// "" (Returns a blank string)
|
||||
// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
|
||||
// "-sm"
|
||||
@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {
|
||||
@return if(breakpoint-min($name, $breakpoints) == null, "", "-#{$name}");
|
||||
}
|
||||
|
||||
|
||||
// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.
|
||||
// Makes the @content apply to the given breakpoint and wider.
|
||||
@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {
|
||||
$min: breakpoint-min($name, $breakpoints);
|
||||
@if $min {
|
||||
@media (min-width: $min) {
|
||||
@content;
|
||||
}
|
||||
} @else {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,3 +67,92 @@
|
||||
@warn "First value in `#{$map-name}` must start at 0, but starts at #{$first-value}.";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Breakpoint Mixins
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
// Breakpoint viewport sizes and media queries.
|
||||
//
|
||||
// Breakpoints are defined as a map of (name: minimum width), order from small to large:
|
||||
//
|
||||
// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)
|
||||
//
|
||||
// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash infront.
|
||||
// Useful for making responsive utilities.
|
||||
//
|
||||
// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
|
||||
// "" (Returns a blank string)
|
||||
// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
|
||||
// "-sm"
|
||||
@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {
|
||||
@return if(breakpoint-min($name, $breakpoints) == null, "", "-#{$name}");
|
||||
}
|
||||
|
||||
|
||||
// Minimum breakpoint width. Null for the smallest (first) breakpoint.
|
||||
//
|
||||
// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
|
||||
// 576px
|
||||
@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {
|
||||
$min: map-get($breakpoints, $name);
|
||||
@return if($min != 0, $min, null);
|
||||
}
|
||||
|
||||
|
||||
// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.
|
||||
// Makes the @content apply to the given breakpoint and wider.
|
||||
@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {
|
||||
$min: breakpoint-min($name, $breakpoints);
|
||||
@if $min {
|
||||
@media (min-width: $min) {
|
||||
@content;
|
||||
}
|
||||
} @else {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Maximum breakpoint width. Null for the largest (last) breakpoint.
|
||||
// The maximum value is calculated as the minimum of the next one less 0.1.
|
||||
//
|
||||
// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
|
||||
// 767px
|
||||
@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {
|
||||
$next: breakpoint-next($name, $breakpoints);
|
||||
@return if($next, breakpoint-min($next, $breakpoints) - 1px, null);
|
||||
}
|
||||
|
||||
|
||||
// Name of the next breakpoint, or null for the last breakpoint.
|
||||
//
|
||||
// >> breakpoint-next(sm)
|
||||
// md
|
||||
// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
|
||||
// md
|
||||
// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))
|
||||
// md
|
||||
@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {
|
||||
$n: index($breakpoint-names, $name);
|
||||
@return if($n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);
|
||||
}
|
||||
|
||||
|
||||
// Media of at most the maximum breakpoint width. No query for the largest breakpoint.
|
||||
// Makes the @content apply to the given breakpoint and narrower.
|
||||
@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {
|
||||
$max: breakpoint-max($name, $breakpoints);
|
||||
@if $max {
|
||||
@media (max-width: $max) {
|
||||
@content;
|
||||
}
|
||||
} @else {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user