I'm theming my app defining colors and typography. But it's not working for the heading in my app header component based on mat-toolbar. My theme is overridden by default theme css rules for .mat-toolbar h1.
index.html
<html>
...
<body class="mat-typography">
<app-root></app-root>
</body>
</html>
_theme.scss file:
#import '~#angular/material/theming';
#import 'utils/palette';
// Plus imports for other components in your app.
// Define the palettes for your theme using the Material Design palettes available in palette.scss
// (imported above). For each palette, you can optionally specify a default, lighter, and darker
// hue. Available color palettes: https://material.io/design/color/
$fem-theme-primary: mat-palette($fem-palette-primary);
$fem-theme-accent: mat-palette(
$fem-palette-primary
); // NOT USED, same as $fem-theme-primary!
$fem-theme-warn: mat-palette($fem-palette-warn);
// Create the theme object (a Sass map containing all of the palettes).
$fem-theme: mat-light-theme(
$fem-theme-primary,
$fem-theme-accent,
$fem-theme-warn
);
// Include theme styles for core and each component used in your app.
// Alternatively, you can import and #include the theme mixins for each component
// that you are using.
#include angular-material-theme($fem-theme);
// Define a custom typography config that overrides the font-family as well as the
// `headlines` and `body-1` levels.
$fem-typography: mat-typography-config(
$font-family: $font-family,
$headline: mat-typography-level(32px, 48px, 700),
);
#include angular-material-typography($fem-typography);
// Include the common styles for Angular Material. We include this here so that you only
// have to load a single css file for Angular Material in your app.
// Be sure that you only ever include this mixin once!
#include mat-core($fem-typography);
topbar.component.html
<div class="topbar">
<mat-toolbar>
<h1 class="topbar__logo mat-headline">App Title</h1>
<mat-form-field
class="topbar__search"
appearance="outline"
color="primary"
>
<input
matInput
data-e2e="topbar-search-input"
class="topbar__search-field"
placeholder="Søg"
(input)="handleSearchChange($event)"
/>
<mat-icon matSuffix inline="true">search</mat-icon>
</mat-form-field>
<div>
<span class="topbar__current-user">{{ currentUser.name }}</span>
<a
mat-button
class="topbar__log-out"
href=""
data-e2e="btn-logout"
(click)="logout()"
>Log ud</a
>
</div>
</mat-toolbar>
</div>
Font family is working... But I expect the <h1 class="topbar__logo mat-headline">App Title</h1> to have css:
font-size: 32px;
line-height: 48px;
font-weight: 700;
Instead it has the default styling:
css:
font-size: 20px;
line-height: 32px;
font-weight: 500;
How can I make ALL Angular Material components (including mat-toolbar) use my own theme?
Component mat-toolbar deliberately overrides all heading tags (h1 through h6) to "title" typography, which maps to h2.
You can make it show "regular" typography for h1 with:
#import '~#angular/material/theming';
.mat-toolbar h1 {
#include mat-typography-level-to-styles($fem-typography, headline); // where headline maps to h1
}
Here are all the mappings, if you'd like to apply the above for other heading sizes:
headline: h1
title: h2
subheading-2: h3
subheading-1: h4
caption: h5
Related
This is for an Angular 11 application. I have a shared css file I'm including in several components as follows:
#Component({
selector: 'app-my-x-selector',
templateUrl: './my-component-x.html',
styleUrls: ['component-x.css', 'shared.css']
})
Adding the following test class to one of the components' css file increases
the bundle size by by 61 bytes, which matches the size of the added source snippet. But moving the class to the shared css increases the bundle size by 140 bytes. Why? It seems like Angular effectively clones the class for each component that includes the shared css file which imho severly limits, if not defeats the purpose of having shared css.
.tr-test00 {
display: block;
margin-left: 45rem;
padding-left: 3rem;
}
#Ya, Imagine you has simple two components with a .css like
//component-one
template: `<h1>Hello</h1>`,
styles: [`h1 { color:blue }`]
//component-two
template: `<h1>By</h1>`,
styles: [`h1 { color:red }`]
Angular make an unique bundle similar to
h1[_ngcontent-edf-c40] {
color: green;
}
h1[_ngcontent-edf-c41] {
color: red;
}
And create an .html like
<hello _ngcontent-bwn-c39="">
<h1 _ngcontent-edf-c40="">Hello</h1> //<--this is the component one
</hello>
<other_ngcontent-bwn-c42="">
<h1 _ngcontent-edf-c41="">By</h1> //<--this is the component two
</other>
This makes that in component-one you see the h1 green and in component-two h1 red
When you refered a common .css to two differents components, Angular makes a bundle like
h1[_ngcontent-edf-c40] {
color: green;
}
h1[_ngcontent-edf-c41] {
color: green;
}
And again the .html is
<hello _ngcontent-bwn-c39>
<h1 _ngcontent-edf-c40>Hello</h1> //<--this is the component one
</hello>
<other _ngcontent-bwn-c48>
<h1 _ngcontent-edf-c41>By</h1> //<--this is the component two
</other>
This is the reason because the bunlde increase two times. If you want, you can take another aproach that is use a common .css and add in your angular.json in the way
.common h1{
color:green
}
And enclosed yours component in a div
<div class="common">
<h1>Hello</h1>
</div>
<div class="common">
<h1>By</h1>
</div>
The .html it's looks like
<hello _ngcontent-jxl-c46="">
<div class="common">
<h1>Hello</h1>
</div>
</hello>
<other _ngcontent-jxl-c46="">
<div class="common">
<h1>By</h1>
</div>
</other>
I am using b-tooltip tags of BootstrapVue to show information. I want to increase the width of b-tooltip (for long text message), text alignment, etc . How can i do it (basically how can i style it)?
<b-button id="tooltip-target-1">
Hover Me
</b-button>
<b-tooltip target="tooltip-target-1" triggers="hover">
I am tooltip <b>component</b> content!
</b-tooltip>
If you're using SCSS in your project, then the easiest way for a global solution would be to modify the SCSS variables to your liking.
If you want to only apply styles to a specific tooltip, or apply something there isn't a variable for. You can use the custom-class prop on b-tooltip to supply it with a custom class, which allows you to style it to your liking.
If you're placing this CSS in a scoped style tag <style scoped> you will need to use a deep selector to target the subcomponents such as .tooltip-inner.
new Vue({
el: '#app',
})
.custom-tooltip > .tooltip-inner{
/* Removes the default max-width */
max-width: none;
/* Apply whatever other styles you want */
font-size: 150%;
padding: 10px;
}
/* This styling is just for the example */
#app {
display: flex;
height: 100vh;
width: 100vw;
align-items: center;
justify-content: center;
}
<link href="https://unpkg.com/bootstrap#4.4.1/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap-vue#2.14.0/dist/bootstrap-vue.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue#2.14.0/dist/bootstrap-vue.js"></script>
<div id="app">
<div>
<b-button id="tooltip-target-1">
Hover Me
</b-button>
<!-- Use the variant prop to use your theme colors -->
<!-- If you want a custom color, you can use CSS -->
<b-tooltip target="tooltip-target-1" variant="primary" custom-class="custom-tooltip" triggers="click">
I am tooltip <b>component</b> content!
</b-tooltip>
</div>
</div>
The trick to change styles of bootstrapvue tooltip.
<style>
.tooltip-inner {
max-width: 800px;
}
</style>
Don't use scoped in style because the component render the html of tooltip outside of app so if you put scoped your css will not work.
I have a website where each section has its own primary color.
I'd like to put something in Bootstrap 4's Sass code, to override the primary color depending on a body class I set.
I have this, but it's not working so far:
$theme-colors: () !default;
$theme-colors: map-merge((
// primary: $blue,
// secondary: $gray-600,
success: $green,
info: $cyan,
warning: $yellow,
danger: $red,
light: $gray-100,
dark: $gray-800
), $theme-colors) !default;
// override according to portal
html {
&.portal-1 {
$theme-colors: map-merge((
primary: #f1b36d
), $theme-colors);
}
How can this be implemented in Bootstrap 4's Sass file?
You can't change the sass variables which are already converted to static CSS dynamically at the client side.
However, to build theme system you can apply one of the following options:
1. Generate independent theme
Put a theme argument in your build system which will generate different themes CSS Ex: grunt build-sass --theme=brown
var themes = {
"default": "https://bootswatch.com/flatly/bootstrap.min.css",
"cerulean" : "https://bootswatch.com/cerulean/bootstrap.min.css"
}
// Use something like this to add theme: (You can also append instead of overriding whole head html)
var headHTML = document.getElementsByTagName('head')[0].innerHTML;
headHTML += '<link type="text/css" rel="stylesheet" href="' + themes.cerulean +'">';
document.getElementsByTagName('head')[0].innerHTML = headHTML;
2. Change properties based upon the parent class
You can have a base CSS which defines general CSS. And then you can have separate CSS Properties based upon the parent
In the following example update green-theme class to blue-theme and vice versa
div[class^=component] {
display: inline-block;
width:150px;
height: 150px;
margin: 1em;
border: 1px solid black;
box-shadow: 1px 1px 5px gray;
border-radius:1em;
}
/* Colors*/
$blue1: #3066BE;
$blue2: #090C9B;
$green1: #5C946E;
$green2: #80C2AF;
/* Blue Theme */
.blue-theme {
.component1 {
background-color: $blue1;
}
.component2 {
background-color: $blue2;
}
}
/* Green Theme */
.green-theme {
.component1 {
background-color: $green1;
}
.component2 {
background-color: $green2;
}
}
<div class="green-theme" id="mainBody">
<div class="component1">
</div>
<div class="component2">
</div>
</div>
*Run Snippet won't work as we are using SCSS *
Make a scss file structure like this,
- vendors
- bootstrap
- stylesheets /*[Bootstrap 4 official sass files]*/
- _bootstrap.scss
- scss
- themes
- _theme-1.scss
- _theme-2.scss
- _variables.scss
- styles.scss
- portal-1.scss
- portal-2.scss
_variables.scss
#import "../vendors/bootstrap/stylesheets/bootstrap/variables";
#import "../vendors/bootstrap/stylesheets/bootstrap/mixins";
/* override bootstrap default variables ... */
/* custom variables with !default ... */
styles.scss
#import "variables";
#import "../vendors/bootstrap/stylesheets/bootstrap";
/* custom styles ... */
themes/_theme-1.scss
#import "../variables";
/* change value bootstrap and custom default variables ... */
$brand-primary: #428bca
$brand-success: #5cb85c;
$brand-info: #5bc0de;
$brand-warning: #f0ad4e;
$brand-danger: #d9534f;
$body-bg: #eff;
themes/_theme-2.scss
#import "../variables";
/* change value bootstrap and custom default variables ... */
$brand-primary: #C04848;
portal-1.scss
#import "themes/_theme-1";
/* change style with new variable bootstrap default components ... */
.portal-1 {
#import "../vendors/bootstrap/stylesheets/bootstrap/buttons";
#import "../vendors/bootstrap/stylesheets/bootstrap/alerts";
/* custom style overrides ... */
}
portal-2.scss
#import "themes/_theme-2";
/* change style with new variable bootstrap default components ... */
.portal-2 {
#import "../vendors/bootstrap/stylesheets/bootstrap/buttons";
#import "../vendors/bootstrap/stylesheets/bootstrap/alerts";
/* custom styles from style.scss overrides ... */
}
After sass compilation we will get 3 files styles.css, portal-1.css and portal-2.css.
Use style.css by default and others include in head tag for theming.
<html>
<head>
<link href="styles.css" rel="stylesheet" />
<link href="portal-1.css" rel="stylesheet" />
</head>
<body>
<button class="btn btn-primary">BUTTON</button>
<div class="portal-1">
<button class="btn btn-primary">BUTTON</button>
</div>
</body>
</html>
NOTE: After searching a while for a simple solution, I though I could avoid the pain for anyone trying to achieve this:
You can use CSS variables to achieve this.
There is a thread on the main bootstrap github page Github Issue and user #johanlef has posted a gist showing his method and the relevant code gist.
Then you can just make sure the css variables is initialized in you page
.body.theme1{
--primary: #5d8be5;
}
I used for one of my multi tenanted website and it works great.
I am using vuejs with vuetify a material design support for vuejs, but I am confused as to how I can add custom css styles to material design without breaking a convention of the material design itself.
It is like bootstrap where we can call .row{} and override the styling or does it differ in some ways.
I don't think there're many differences from bootstrap since vuetify will automatically add necessary class names for you. Suppose you want to override the background color of the following template.
<v-layout row justify-space-around></v-layout>
Just override it with .row
.row {
background: #123456;
}
Check the sample below.
new Vue({ el: '#app' })
.row {
background: #123456;
}
.theme--dark {
width: 400px;
}
.card__text {
font-weight: 800;
}
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script src="https://unpkg.com/vuetify/dist/vuetify.js"></script>
<link href="https://unpkg.com/vuetify/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
<v-app>
<main>
<v-layout row justify-space-around>
<v-card dark class="primary">
<v-card-text>one</v-card-text>
</v-card>
</v-layout>
</main>
</v-app>
</div>
Please notice that - was converted to __ (e.g. v-card-text) and theme-- was prepended to the theme's name (e.g. dark).
With reference to this plunker:
https://plnkr.co/edit/GWsbdDWVvBYNMqyxzlLY?p=preview
I have the same css specified in the styles.css file, and in the src/app.ts file.
If I comment in the css in styles.css and comment out the css in src/app.ts, it works.
styles.css:
/* If these are commented in, and the ones in src/app.ts are
* commented out, the three items are spaced appropriately. */
/***
md-toolbar-row {
justify-content: space-between;
}
md-toolbar {
justify-content: space-between;
}
***/
If I comment out the css in styles.css and comment in the css in src/app.ts, it fails.
src/app.ts:
#Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
<md-toolbar color="primary">
<span><md-icon>mood</md-icon></span>
<span>Yay, Material in Angular 2!</span>
<button md-icon-button>
<md-icon>more_vert</md-icon>
</button>
</md-toolbar>
</div>
`,
// If these are commented in, and the ones in style.css are
// commented out, the three items are scrunched together.
/***/
styles: [
`md-toolbar-row {
justify-content: space-between;
}`,
`md-toolbar {
justify-content: space-between;
}`
]
/***/
})
export class App {
name:string;
constructor() {
this.name = `Angular! v${VERSION.full}`
}
}
I'm having trouble visualizing the difference between defining the css for the whole application, and for the specific component. Can someone tell me what's going on?
=================================
#bryan60 and #Steveland83 seem to indicate that the problem lies somewhere in the view encapsulation. And upon further investigation, it does in a sense.
If you look at the code below, you will see that the styles for md-toolbar and md-toolbar-row have an attribute attached. But the html for md-toolbar and md-toolbar-row does not match. Only md-toolbar has the attribute attached. md-toolbar-row doesn't. I have marked the relevant four lines with >>>>>.
So that's the problem but:
1. Do I report it to the material design people as an error?
2. Is there some workaround I can use today?
<html>
<head>
:
<script src="config.js"></script>
<script>
System.import('app')
.catch(console.error.bind(console));
</script>
<link href="https://rawgit.com/angular/material2-builds/master/prebuilt-themes/indigo-pink.css" rel="stylesheet">
<style>
>>>>> md-toolbar-row[_ngcontent-c0] {
justify-content: space-between;
}
</style>
<style>
>>>>> md-toolbar[_ngcontent-c0] {
justify-content: space-between;
}
</style>
<style>
.mat-toolbar {
display: flex;
: :
.mat-mini-fab,
.mat-raised-button {
outline: solid 1px
}
}
</style>
</head>
<body class="mat-app-background">
<my-app _nghost-c0="" ng-version="4.4.0-RC.0">
<div _ngcontent-c0="">
<h2 _ngcontent-c0="">Hello Angular! v4.4.0-RC.0</h2>
>>>>> <md-toolbar _ngcontent-c0="" class="mat-toolbar mat-primary" color="primary" role="toolbar" ng-reflect-color="primary">
<div class="mat-toolbar-layout">
>>>>> <md-toolbar-row class="mat-toolbar-row">
<span _ngcontent-c0=""><md-icon _ngcontent-c0="" class="mat-icon material-icons" role="img" aria-hidden="true">mood</md-icon></span>
<span _ngcontent-c0="">Yay, Material in Angular 2!</span>
<button _ngcontent-c0="" class="mat-icon-button" md-icon-button=""><span class="mat-button-wrapper">
<md-icon _ngcontent-c0="" class="mat-icon material-icons" role="img" aria-hidden="true">more_vert</md-icon>
</span>
<div class="mat-button-ripple mat-ripple mat-button-ripple-round" md-ripple="" ng-reflect-trigger="[object HTMLButtonElement]" ng-reflect-centered="true" ng-reflect-disabled="false"></div>
<div class="mat-button-focus-overlay"></div>
</button>
</md-toolbar-row>
</div>
</md-toolbar>
</div>
</my-app>
</body>
</html>
One of the Angular features is View Encapsulation which basically means that you can define styles scoped only to a specific component without affecting any other components.
By default styles are scoped only for the component they are referenced in, but you can choose to override that to make them available globally by setting your components encapsulation to None.
E.g.
import { Component, ViewEncapsulation } from '#angular/core';
#Component({
selector: 'component-that-shares-styles',
templateUrl: './component-that-shares-styles.component.html',
styleUrls: ['./component-that-shares-styles.component.scss'],
encapsulation: ViewEncapsulation.None // <-- Set encapsulation here
})
*Note that you will need to import ViewEncapsulation from #angular/core
Okay, with help from #Steveland83 and #bryon60, I came to a definite answer. The Material Design people are aware of this problem. They have made a writeup.
https://github.com/angular/material2/blob/master/guides/customizing-component-styles.md
Here's their summary:
Styling other components
If your component has view encapsulation turned on (default), your component styles will only
affect the top level children in your template. HTML elements belonging to child components cannot
be targeted by your component styles unless you do one of the following:
Add the overriding style to you global stylesheet. Scope the selectors so that it only affects
the specific elements you need it to.
Turn view encapsulation off on your component. If you do this, be sure to scope your styles
appropriately, or else you may end up incidentally targeting other components elswhere in your
application.
Use a deprecated shadow-piercing descendant combinator to force styles to apply to all the child
elements. Read more about this deprecated solution in the
Angular documentation.
I don't want to use global css, or a deprecated solution. I guess I will style with classes, and not elements. If someone has a better idea, tell me!