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>
Related
I'd like to implement something like the BEM model in my Sass library. But I'm struggling to find a clean way to do this.
For example, I'd like to declare a 'base' style for a common element, and then extend it with useful variations:
.container {
margin: 10%;
background: #eee;
&-featured {
border: 2px solid #999;
}
}
The problem here is that the generated .container-featured class only contains the border property—Sass doesn't include the margin and background from its 'parent' class.
So you end up having to double up on classes in your markup to get the desired results:
<div class="container container-featured">
...
</div>
Is there some way to pull the properties from a parent class down into that modifier class, so you can get the same visual result just referencing the modifier class in your markup?
<div class="container-featured">
<!-- has margin, background, and border styles via just modifier class -->
</div>
I've tried using mixins to do this, but things get verbose and repetitive very quickly:
#mixins container {
margin: 10%;
background: #eee;
}
.container {
#include container;
&-featured {
#include container;
border: 2px solid #999;
}
}
Is there a simple, clean way of achieving this with Sass?
What you are looking for is the #extend directive. #extend allows you share a set of CSS properties from one selector to another. This means that you would only need to use the container-featured class.
Example
.container {
margin: 10%;
background: #eee;
&-featured {
#extend .container;
border: 2px solid #999;
}
}
compiles to:
.container,
.container-featured {
margin: 10%;
background: #eee;
}
.container-featured {
border: 2px solid #999;
}
You should use mixin in BEM not in Sass!
Mixins are just that - usage of several blocks and/or elements on the same DOM node.
A single DOM node can represent:
several blocks b-menu b-head-menu
a block and an element of the same block b-menu b-menu__layout
a block and an element of another block b-link b-menu__link
elements of different blocks b-menu__item b-head-menu__item
a block with a modifier and another block b-menu b-menu_layout_horiz b-head-menu
several different blocks with modifiers b-menu b-menu_layout_horiz b-head-toolbar b-head-toolbar_theme_black
Read more at: http://bem.github.io/bem-method/html/all.en.html, section Mixin.
Also you can use i-blocks (abstract blocks), so your .container will be .i-container, read more: http://bem.github.io/bem-method/html/all.en.html, section Naming conventions.
And with Sass you can implement i-block as
<div class="container-featured">
...
</div>
%i-container {
// abstract block styles
margin: 10%;
background: #eee;
}
.container-featured {
#extend %i-container;
border: 2px solid #999;
}
Without Sass, mixin in the BEM are made as follows:
<div class="i-container container-featured">
...
</div>
.i-container {
// abstract block styles
margin: 10%;
background: #eee;
}
.container-featured {
border: 2px solid #999;
}
In the following code example I generate two squares that ideally should turn red.
The first div .with-root currently stays blue, the second div .without-root turns red. I expect this behaviour, but don't see a proper solution to turn the .with-root div red as well.
Note the difference in the scss file: the first div works with a fixed parent selector, the second one doesn't have a parent. For CSS specificity I need to work with the .with-root {} wrapper.
.with-root {
.with-root__element {
display: block;
width: 5rem;
height: 5rem;
background: blue;
&--red & {
&__item {
background: red;
}
}
}
}
.without-root {
&__element {
display: block;
width: 5rem;
height: 5rem;
background: blue;
&--red & {
&__item {
display: block;
width: 5rem;
height: 5rem;
background: red;
}
}
}
}
The codepen can be found here: https://codepen.io/studiotwist/pen/OzMOmr
Well now that I hopefully understood your question I deleted my wrong idea before and the following solution should work.
Maybe there could be a logic erorr. You have actually three class definitions of .with-root__element and two of them are extended with --red and __item, but the 3rd one is however an extra class which comes in conflict with the other two. You're basically concatenating the endings --red and __item with the parent selector *__element. Also, the --red class is nested inside the *__element one without ending in your CSS but in HTML it is not. *__element and *__element--red are attached in the same HTML tag.
DEBUG
Only showing the first DIV.
.with-root {
.with-root__element {
display: block;
width: 5rem;
height: 5rem;
background: blue;
&--red {
//#error &; // this reference contains the entire document root including the root element .with-root which is wrong
#{&} &__item {
//#error #{&} &__item; // this is a wrong concatenation plus it takes the entire root with it
background: red; // thus, this won't render
}
}
}
}
Debug in action # Sassmeister
POSSIBLE FIX
#mixin bg($bg) {
width: 5rem;
height: 5rem;
background: $bg;
}
.with-root__element {
#include bg(blue);
$this: &;
#at-root {
.with-root {
#{$this}--red #{$this}__item {
#include bg(red);
}
}
}
}
.without-root {
&__element {
#include bg(blue);
&--red &__item {
#include bg(red);
}
}
}
Fork
#at-root is a directive which is useful for your issue as it basically crops the nesting level of the selector and styles can be defined inside the root-body by referencing the parent selector instead of the entire root. So I added a variable $this which will cache the reference. display: block is not needed as div elements have it by default. Sorry about the mixin, it's a habit. --red and __item have now the refence selector *__element.
#at-root Documentation
First of all, sorry for yet another post about this topic but I couldn't see anything that makes sense to me in polymer documentation and on stackoverflow.
I just want to attach style to my element.
From the documentation (https://www.polymer-project.org/0.5/articles/styling-elements.html and https://www.polymer-project.org/0.5/docs/polymer/styling.html#including-stylesheets-in-an-element)it should be straight forward.
<polymer-element name="x-foo">
<template>
<style>
x-foo div { ... }
</style>
...
But it doesn't work as expected. If we define the style for an element, inside the element, it is not applied.
Here is the code:
<polymer-element name="x-button" noscript>
<template>
<style>
/* not working */
x-button {
background-color: green;
}
/* not working */
x-button .hithere{
display: block;
min-height: 50px;
background-color: red;
margin: 20px;
}
/* not working */
x-button .hitheretoo{
display: block;
min-height: 50px;
background-color: blue;
margin: 20px;
}
</style>
<div class="hithere"></div>
<template>
<div class="hitheretoo"></div>
</template>
</template>
</polymer-element>
And a live demo:
http://codepen.io/anon/pen/yyZqMN
Thanks
ssorallen explained the css issue very well and there is more. I couldn't get :host to work on it's own and depending on the browsers you will need to shim the Shadow DOM & add polyfill-next-selector styles.
Additionally, The element never gets registered because you have not used the Polymer() function inside the custom element (unless you chose not to add it in your code example). Here is a codepen of what I found to be one possible solution.
The one thing I am still trying to figure out is the nested <template> issue. I can't pierce the shadow boundary with ::shadow or /deep/. Might be a bug. I'll take a look when I get a few minutes.
Use the :host selector when styling an element from inside itself
<style>
:host {
background-color: green;
}
.hithere {
display: block;
min-height: 50px;
background-color: red;
margin: 20px;
}
.hitheretoo {
display: block;
min-height: 50px;
background-color: blue;
margin: 20px;
}
</style>
When you're styling from inside a custom element all selectors are already scoped to the element. By selecting x-button you are selecting any x-buttons that are descendants of this element, not the element itself. That also means you don't need to prefix selectors with the tag name to scope them; the shadow DOM provides scoping.
i need to know what the proper term for this code is. someone sent this to me and it was what ii was looking for, but i need the proper term so i can learn it myself. what i'm looking for is the multiple colors on a webpage.
<!doctype html>
<html>
<head>
<title>I am Awesome!</title>
<style type="text/css">
body, #nav, #header, .white-box, .blue-box {
width: 100%;
margin: 0;
padding: 0;
}
body {
height: 100%;
}
h1{
margin: 0;
padding: 150px 0;
}
#nav
{
height: 60px;
color: #fff;
position: fixed;
background: darkblue;
}
#header {
background: red;
text-align: center;
}
#header, .white-box, .blue-box {
height: 400px;
}
.white-box {
background: #ccc;
}
.blue-box {
background: lightblue;
}
</style>
</head>
<body>
<div id='nav'>Navigation</div>
<div id='header'>
<h1>Some Cool Image!</h1>
</div>
<div class='white-box'>Content!</div>
<div class='blue-box'>More Content!</div>
<div class='white-box'>And Something Else!</div>
<div class='blue-box'>Redundancy!</div>
</body>
</html>
There is no proper term for having multi-colors on a web page. You have a simple css code defining various classes with various colors for different parts of your site. So be easy, Not every thing needs to have a name. If its still confusing, let me know in commnents
The proper term for this is Cascading Style Sheets, also known as CSS. CSS is used to style an HTML document and make it look fancier and do formatting changes that HTML cannot do (i.e change the color of the text or change the font size)
CSS can be edited in programs such as JSfiddle.
To insert CSS into an HTML document, the tag can be used or you can reference the CSS stylesheet using href.
CSS can be applied to 3 different things:
By element type (i.e. p{}
By ID: #main{} OR
By class: .button{}
The CSS code is put inbetween the curly braces.
For example, to change the color of element p to blue I would use
p {
color:blue;
}
It's Cascading Style Sheets, otherwise known as CSS. There are a few different ways to apply the styles:
By element type: body { ... }
By ID: #nav { ... }
By class: .white-box { ... }
You can read more about it online; one example is here: http://w3schools.com/css/css_syntax.asp
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).