Presentation
I'm trying to build a web site available in multiple cultures, with different reading direction.
To do so, I simply add the dir="rtl" attribute on my root HTML element.
My issue is that I have some CSS rules that are specific to one direction or the other (margins or paddings, most of the times).
Unsuccessful try with attribute selector
I though that I could simply use the attribute selector but the dir attribute is only set on the root element, so this wouldn't work :
selector {
&[dir="ltr"] {
// LTR specific
}
&[dir="rtl"] {
// RTL specific
}
}
For instance, on this demo, the title should have a margin of 5px on the right if the application is in rtl or on the left if it's in standard ltr.
Other idea
I've noticed that the direction is rightfully set at rtl, is there a way to use that rule within a CSS or Sass selector ?
Edit and precisions
It seems that I've forgotten an important point. I'm building the web site using Vue.js, the dir attribute is bind in the main component (App) and the RTL/LTR specific CSS rules can be in the same component or in other self-contained component.
Following your css code you could do this with SASS at-root directive DEMO. So this:
#app {
width: 300px;
height: 100px;
border: 1px solid red;
h1 {
#at-root {
[dir="rtl"]#{&} {color: green}
}
#at-root {
[dir="ltr"]#{&} {color: red}
}
}
}
It will compile to this css.
#app {
width: 300px;
height: 100px;
border: 1px solid red;
}
[dir="rtl"]#app h1 {
color: green;
}
[dir="ltr"]#app h1 {
color: red;
}
You could style everything LTR, and only adjust some elements styling for RTL. Might this work for you?
[dir="rtl"] {
&selector {
// RTL specific
}
&selectorN {
// RTL specific
}
}
Use below scss to get expected output
#app {
width: 300px;
height: 300px;
background: red;
&[dir="ltr"] h1{
margin-left: 10px;
}
&[dir="rtl"] h1 {
margin-right: 10px;
}
}
Probably you are going a little in the wrong direction.
Most of the time, you can achieve this automatically, no need for specific selectors.
Margin, for instance:
Just set it both for left and right margin. The browser will choose the correct one for you
#app {
width: 300px;
background: tomato;
margin: 10px;
}
h1 {
margin-left: 15px;
margin-right: 5px;
}
<div id="app" dir="ltr">
<h1>
margin left 15
</h1>
</div><div id="app" dir="rtl">
<h1>
margin right 5
</h1>
</div>
I am attempting to override the default max-width of the snackbar component in Angular Material.
The CSS applied by Angular Material is shown below:
.mat-snack-bar-container {
border-radius: 2px;
box-sizing: border-box;
display: block;
margin: 24px;
max-width: 568px;
min-width: 288px;
padding: 14px 24px;
transform: translateY(100%) translateY(24px);
}
I have tried overriding using the same style in my style.css file but this style is overridden by the default style.
.mat-snack-bar-container {
max-width: 800px;
}
I have found an answer to a similar question but I know the answer to that question is now deprecated (/deep/ is deprecated).
Is there a best practices solution to this?
To do this properly, you need to set the View Encapsulation to None on your component:
#Component({
templateUrl: './my.component.html' ,
styleUrls: ['./my.component.css'],
encapsulation: ViewEncapsulation.None,
})
Then in your component css you can just do this:
.mat-snack-bar-container {
max-width: 800px;
}
From the official docs:
View Encapsulation = None means that Angular does no view
encapsulation. Angular adds the CSS to the global styles. The scoping
rules, isolations, and protections discussed earlier don't apply. This
is essentially the same as pasting the component's styles into the
HTML.
Put css in your styles.scss or styles.css
.snackbar {
max-width: 90% !important;
margin-left: auto !important; // center align from left
margin-right: auto !important; // center align from right
margin-bottom: 1rem !important;
padding: 10px !important; // spacing between the text and boundary
background-color: green;
color: white;
.mat-button-wrapper {
color: black !important; // action text color
}
}
Note: make sure you have set !important with every style, without it, style wouldn't work.
in component.ts
this.snackbar.open(this.resMsg.message, 'OK', {
panelClass: 'snackbar'
})
Verified for #angular/material v7.0.x:
CSS !important modifier does the trick.
Put this is src/styles.scss (the app's global css):
.mat-snack-bar-container {
max-width: 100% !important;
}
Also we tweak its font:
/* Overrides SnackBar CSS in Material Design's .mat-simple-snackbar class */
/* Original sizes: font: 24px, height: 47.952px */
.mat-simple-snackbar {
display: flex;
font-size: 28px !important; // 28px is double, 42px for triple
min-height: 70px !important; // 70px for double, 90px for triple
align-items: center !important;
justify-content: center !important;
}
As of June 30, 2019, using Angular Material 8.0.1 with Angular 8.0.3, the following SCSS and typescript seems to work for overriding the color of the action button in an Angular Material snackbar *without using !important *:
styles.scss (not the extremely long duration, which allowed me to inspect the styling before it disappeared):
$snackBarTextColor: white;
$snackBarBackgroundNormal: #087a51;
$snackBarActionColor: lightgray;
.snackBarInfo {
background-color: $snackBarBackgroundNormal;
color: $snackBarTextColor;
}
.mat-simple-snackbar > span {
font-weight: bold;
}
.mat-simple-snackbar-action {
.mat-button {
.mat-button-wrapper {
color: $snackBarActionColor;
}
}
}
app.module.ts:
import { MAT_SNACK_BAR_DEFAULT_OPTIONS } from '#angular/material/snack-bar';
providers: [
{
provide: MAT_SNACK_BAR_DEFAULT_OPTIONS,
useValue: {
duration: 41000,
horizontalPosition: 'center',
verticalPosition: 'bottom',
panelClass: 'snackBarInfo'
}
}
]
I remember working in a project with web-designers, and they had a money-jar, where devs had to put a coin in if they used the !important statement. ;)
The other solutions did not work for me, unless i set the .cdk-overlay-pane (using material 11):
.cdk-overlay-pane {
width: 100%;
}
.mat-snack-bar-container {
max-width: 100%;
width: 100%;
}
Not sure when Material introduced this (must be a new thing judging by all the answers to this thread), but you can now override the mat-snack-bar-container's styles by passing a parameter in the _snackBar.open(), like this:
component.ts
openSnackBar(message: string, action: string) {
this._snackBar.open(message, action {
panelClass: 'my-custom-container-class',
});
}
component.scss
::ng-deep .my-custom-container-class{
max-width: 100% !important;
min-width: 0% !important;
min-height: 0 !important;
padding: 0 !important;
margin: 32px !important;
box-shadow: none;
}
I'm afraid you still have to use the ng-deep and the !importants; but at least you no longer need to do ViewEncapsulation None.
The way to go.
encapsulation: ViewEncapsulation.None
Here is a stackblick to demonstrate
Angular 10 and without special tricks:
use panelClass when opening the snackbar, for example:
this.snackBar.open("VeryLongTextWithoutThePossibilityOfBreakingAutomatically", "X", {
duration: 0,
panelClass: 'notif-error'
});
duration: 0 is only for debugging.
write this into your style.css
.notif-error {
background-color: red;
}
.mat-snack-bar-container.notif-error {
max-width: 100%;
}
Now because of css-specificity, this will be the most specific rule.
Beware that there should not be space between .mat-snack-bar-container and .notif-error.
This rule will apply to elements which has both the .mat-snack-bar-container and .notif-error classes.
This also works when your .notif-error class is empty.
Using vw works for me,on both bigger and small screen size
.mat-snack-bar-container {
margin-right: auto !important;
margin-left: auto !important;
width: 80vw !important;
max-width: 100vw !important;
}
FYI Starting with Angular Material v15 with the migradtion to MDC, the class .mat-snack-bar-container has been renamed to
.mat-mdc-snack-bar-container
I also had to use some of the new inner MDC snackbar classes to properly recolor the snackbar starting in v15:
SCSS:
// Classname used in the MatSnackBarConfig obj of MatSnackBar.open():
// panelClass: ['my-snackbar-class']
my-snackbar-class.mat-mdc-snack-bar-container {
.mdc-snackbar__surface {
// Background color of entire snackbar:
background-color: red;
.mdc-snackbar__label {
// Color of snackbar text:
color: white;
}
button {
// Color of snackbar button text:
color: white !important;
}
}
}
Suppose we have a block element named .button which we want to reuse with different margin values on multiple different pages.
Possible solutions:
//1. Nested styles
.page-1 {
.button { margin: 10px; }
}
.page-2 {
.button { margin: 20px; }
}
//2. Specific modifier for EACH page
.button {
&--pg-1-margin { margin: 10px; }
&--pg-2-margin { margin: 20px; }
}
// 3. Special, page-specific block level element
// which will be COMBINED with an existing block-level
// element (ex: <button class="button page-1-element">...</button>)
.page-1-element { margin: 10px; }
.page-2-element { margin: 20px; }
Which one of these will be considered BEM-friendly way?
Is the first method acceptable / preferred way if there are too many different margins used?
Here's the answer to your question in official docs: https://en.bem.info/methodology/css/#external-geometry-and-positioning
I have just started to explore GWT, and i'm bit confused with different ways of applying styles to GWT widgets.In gwt docs, there are 4 ways by which you can override default style of a widget,
1) Using a tag in the host HTML page.(Deprecated)
2) Using the element in the module XML file.(Deprecated)
3) Using a CssResource contained within a ClientBundle.
4) Using an inline element in a UiBinder template.
Suppose i have a CSS file in some package say, com.abc.xyz.styles.css .And the file has the following contents,
/**the panel itself**/
.gwt-TabLayoutPanel {
border: none;
margin: 0px;
padding: 0px;
}
/**the tab bar element**/
.gwt-TabLayoutPanel .gwt-TabLayoutPanelTabs {
background-color: #F4F4F4 !important;
}
/**an individual tab**/
.gwt-TabLayoutPanel .gwt-TabLayoutPanelTab {
background-color: #6F6F6E !important;
}
.gwt-TabLayoutPanel .gwt-TabLayoutPanelTab-selected {
background-color: white !important;
}
/**an element nested in each tab (useful for styling)**/
.gwt-TabLayoutPanel .gwt-TabLayoutPanelTabInner {
font-family: Arial !important;
}
/**applied to all child content widgets**/
.gwt-TabLayoutPanel .gwt-TabLayoutPanelContent {
border: none;
margin: 0px;
overflow: hidden;
padding: 15px;
}
How will i inject this css file ? How can this be done using the 3rd and 4th option of styling mentioned above?.
You can simply add your CSS file to the host page. Then you can use the full power of CSS selectors. This is my preferred method of using CSS in GWT:
What the best strategy to structure CSS in GWT?
i'm building a custom theme for wordpress and saw this in the default 2010 style.css file:
#wrapper {
margin: 0 auto;
width: 940px;
}
#wrapper {
background: pink;
margin-top: 20px;
padding: 0 20px;
}
now this is the default code (except the pink). when i try and collapse it, which seems logical, it makes quite a difference.
what i can't figure out is WHY you'd declare the same element twice like that? i've never seen that before...
WR!
It proves useful when you want to apply shared properties at multiple elements. Another useful application is adding stylesheets from multiple sources Example:
#head, #foot {
height: 100px;
}
#foot { /*Another foot*/
color: red;
}
Second example: CSS from multiple sources:
/* External stylesheet: common.css */
body {
background: yellow;
}
/* Inline stylesheet, overrides external stylehseet */
body {
background: pink;
}
When two properties have the same specificity, the lastly declared property will be applied.
It just overrides previously declared properties.
wrapper will now have margin:20px auto 0 auto (Top Right Bottom Left).