Handling directed margin and padding when changing the direction - html

When changing the html dir attribute from ltr to rtl, all directed margins and paddings need to be reversed :
[dir='ltr'] {
margin-left: 80px;
}
[dir='rtl'] {
margin-right: 80px;
}
Is there another better approach?

If you are sure that you need to reverse every instance of e.g. margin and you are using some css preprocessor such as sass. You could create the following mixin:
#mixin horizontal-margin($left: initial, $right: initial) {
&[dir="ltr"] {
margin-left: $left;
margin-right: $right
}
&[dir="rtl"] {
margin-right: $right;
margin-right: $left;
}
}
And then use it like this:
p {
background: blue;
#include horizontal-margin(16px, 48px);
}
and in your html
<p dir="ltr"> some text</p>
Hope this helps.

Related

Nested css selectors by adding to class name in SASS

I am building a flexbox grid system and am looking to keep my scss file manageable.
What is wrong with the selectors for elements with classes col-2, col-4, col-6 that are causing them not to work?
.grid-container{
max-width:1280;
margin: 0 24px;
display: flex;
[class^="col"]{
flex:1;
margin: 0 8px;
&:first-child{
margin-left:0;
}
&:last-child{
margin-right:0;
}
[class*="-2"]{
width:16.5%;
}
[class*="-4"]{
width:33%;
}
[class*="-6"]{
width:50%;
}
}
}
All columns are getting the styling for margin and the first-child and last-child behavior but not the width from the other selectors. Is this perhaps a flexbox issue? flex-basis?
It's not a "flexbox" issue. It's a "CSS" issue.
[class^="col"] {
[class*="-2"] {
width:16.5%;
}
}
will result in this CSS:
[class^="col"] [class*="-2"]{width:16.5%;}
But you probably want...
[class^="col"][class*="-2"]{width:16.5%;}
... which would be produced by...
[class^="col"] {
&[class*="-2"] {
width:16.5%;
}
}
The space (in CSS) and the ampersand & (in SCSS) are the differences.
[class^="col"] {
[class*="-2"] {
width: 16.5%;
}
[class*="-4"] {
width: 33%;
}
[class*="-6"] {
width: 50%;
}
}
Will produce the following selectors:
[class^="col"] [class*="-2"] {}
[class^="col"] [class*="-4"] {}
[class^="col"] [class*="-6"] {}
Notice the space between each attribute selector. The selectors above will first search for and element that has a class attribute that starts with the .col class. They then find an element nested within the .col element with a class attribute that contains -2, -4 or -6 somewhere in the attribute.
By adding an ampersand & you can capture the current selector path. The following SCSS is the same as what you have now:
[class^="col"] {
& [class*="-2"] {
width: 16.5%;
}
}
Compiles to (space between attribute selectors):
[class^="col"] [class*="-2"] {}
Placing the ampersand immediately before the nested selector (like you have with first-child and last-child) gives a different result, the one you (likely) want:
[class^="col"] {
&[class*="-2"] {
width: 16.5%;
}
}
Compiles to (no space between attribute selectors):
[class^="col"][class*="-2"] {}
IMHO what you have currently is over engineered. I'd suggest something more straightforward and flexible. Use regular class selectors.
.col {
&-2 { width: 16.5%; }
&-4 { width: 33%; }
&-6 { width: 50%; }
}
[class*="col-"] {
flex: 1;
margin: 0 8px;
&:first-child { margin-left: 0; }
&:last-child { margin-right: 0; }
}
See below Stack Snippet to see what the above is compiled to. Note that I used *= (asterisk equals) instead of ^= (caret equals) for class placement flexibility. Up to you if you want to enforce column classes to be the first class in the class attribute value.
https://codepen.io/anon/pen/yXveRq
.row {
display: flex;
}
.col-2 { width: 16.5%; }
.col-4 { width: 33%; }
.col-6 { width: 50%; }
[class*="col-"] {
flex: 1;
margin: 0 8px;
}
[class*="col-"]:first-child {
margin-left: 0;
}
[class*="col-"]:last-child {
margin-right: 0;
}
<div class="row">
<div class="col-4">Col 1</div>
<div class="col-4">Col 2</div>
<div class="col-4">Col 3</div>
</div>
CoJanks.
The quick and dirt fix is to set additional definitions to the 'flex' on the .col class in the .grid-container.
Here is a quick and dirty answer to solve your problem for ya!
flex:1 1 auto;
FYI. There were some discrepancies in class nesting as well that I covered in the link provided.

Override css from Pseudo class

I am not a designer, so thisquestion might sound dumb.
I can override color property from pseudo class but not padding.
Here is an example
html:
<p id="pid" class="pclass"></p>
css:
.pclass
{
color:red;
padding-left: 20px;
}
#pid:before
{
content:'test ';
color:green !important;
padding-left: 0px !important;
}
Fiddle
Reason
The styles you've applied from the pseudo-class are applied to the content only. Not to the actual element. You might think that !important is making the color to change, but that is not the case.
So, when you change the color from pseudo-class the color of the content i.e. test is changed. And the padding-left is applied to the test only not the <p> element.
Demo
Inspect the paragraph and notice the padding.
.pclass {
color: red;
padding-left: 20px;
}
.pclass:before {
content: 'test';
color: green;
padding-left: 10px;
}
<p id="pid" class="pclass"></p>
Solution
To solve this issue you can set the position of the element to relative and use negative left.
Demo
.pclass {
color: red;
padding-left: 20px;
}
.pclass:before {
content: 'test';
color: green;
left: -20px;
position: relative;
}
<p id="pid" class="pclass"></p>
use this may help you
#pid::before {
left: -20px;
position: relative;
}
You can simply override the padding using the #pid selector: IDs have an higher precedence than classes:
.pclass {
color:red;
padding-left: 20px;
}
#pid:before {
content: 'test';
color: green;
}
#pid {
padding-left: 0;
}
If you wish to keep the margin after the text added by :before you can add
padding-right: 20px;
to #pid:before.

CSS based on text value of link

I have some html (auto generated) like this :
<a>Save</a> <a>Cancel</a>
These two buttons are auto-generated via a framework so I have little control over the space between these two links. I want to include some more space in between the two buttons.
I have added some css
.fw-link {
margin-left: 6px!important;
margin-right: 6px!important;
}
but again this adds margin to the right of Cancel and Left of Save link - wasting much space.
Is it possible to write some CSS that applies based on the text value of LINK?
Your CSS can be:
a {
margin-left: 6px!important;
margin-right: 6px!important;
}
a:first-child {
margin-left: 0 !important;
}
a:last-child {
margin-right: 0 !important;
}
What this will do is:
1. Add space between all links
2. Remove left margin from first link
3. Remove right margin from last link
Sample codepen link
use something like:
a:nth-child(1) { //1st a
margin-right: 6px //!important needed?
}
a:nth-child(2) { //2nd a
margin-left: 6px //!important needed?
}
Try using the attribute name.
<a name="save">Save</a> nbsp; <a name="cancel">Cancel</a> nbsp;
Then in your CSS file:
a[name=save] {
margin-right: 6px!important;
}
a[name=cancel] {
margin-left: 6px!important;
}

Which is the best way to handle RTL CSS

Right now I'm working on a bilingual website and kinda confuse about how to handle the RTL CSS codes. I have 2 things in my mind as follows;
1. Single CSS file - Overriding LTR default codes.
.content {
position: relative;
padding: 5px 10px 5px 240px;
}
.rtl .content {
padding-right: 240px;
padding-left: 10px;
}
2. Single CSS file - Without overiding
.content {
position: relative;
padding-top: 5px;
padding-bottom: 5px;
}
.ltr .content {
padding-left: 240px;
padding-right: 10px;
}
.rtl .content {
padding-right: 240px;
padding-left: 10px;
}
Using the first method, there will a lot of overrides. Also using the second method there will be a lot of codes in the css file. I know both will do the trick but curious to know which is the best method. Kindly suggest me if there is another method too.
If you are looking for a more robust solution, I would suggest you these approaches:
CSS Preprocessor
Learn and use a CSS preprocessor like LESS (if necessary, use a plugin like Bi-App-Less) and conditionally add the correct stylesheet.
Back-end controlled variable
Use CSS mixed with some back-end variable like:
direction: <%=rtl%>;
padding-<%=right%>: 10px;
padding-<%=left%>: 240px;.
RTL Tool
Use a RTLer tool.
CSS can display your text right to left with this:
.rtl
{
direction:rtl;
}
I prefer to handle padding and margins on a single line:
.content {
position: relative;
padding:5px 10px 5px 240px;
}
.rtl .content {
padding:0 240px 0 10px;
}
You could try doing something like this
.content {
width: 500px;
padding: 5px 10px;
border: 1px solid #ddd;
}
.content.rtl {
float: right;
direction: rtl;
}
try to hardcode the minimum amount of paddings/margins specific to a direction, heres an example http://jsfiddle.net/icodeforlove/UNS5L/

Simplifying CSS root selector

Please refer below css code
#AdminUser .admin-label-margin {
margin-left: 160px;
margin-top: -25px;
padding-bottom: 10px;
}
#AdminUser #entitytitle h4 {
margin-left: 175px;
padding-bottom: 13px;
}
#AdminUser input[type='text'] {
width: 180px;
}
#AdminUser .admin-label-span {
margin-left: -15px !important;
margin-right:12px;
}
Each and every time I am specifying the root element and applies the css to specific control. I don't want to this kind of scenario. How can i simplify the above css and specify root selector in one time ?
CSS does not support this. You can however use a preprocessor like Sass/SCSS.
With SCSS:
#AdminUser {
.admin-label-margin {
/* snip */
}
/* snip */
}
Note that the final code will look similar to the original one, SCSS translates the above code to the one you currently have, so that you can develop more easily.
You could use a CSS pre-processing library like LESS which allows you to express your css using nested statements.
So it will allow you to write
#AdminUser {
.admin-label-margin {
margin-left: 160px;
margin-top: -25px;
padding-bottom: 10px;
}
#entitytitle h4 {
margin-left: 175px;
padding-bottom: 13px;
}
input[type='text'] {
...
}
.admin-label-span {
...
}
}
but once processed it would output the CSS to the browser in the standard non-nested format. ie. it would generate your original CSS :
#AdminUser .admin-label-margin {
margin-left: 160px;
margin-top: -25px;
padding-bottom: 10px;
}
#AdminUser #entitytitle h4 {
margin-left: 175px;
padding-bottom: 13px;
}
#AdminUser input[type='text'] {
width: 180px;
}
#AdminUser .admin-label-span {
margin-left: -15px !important;
margin-right:12px;
}
Bear in mind that if you use LESS you have a few considerations :
running compilation of .less to .css files as part of your build process
or using on the fly conversion with the less javascript
you might get FOUC's
you'll need to check that your webserver is happy serving the less mime type
On the plus side you'll get mixins, variables and all the goodness that LESS brings you alongside the coding syntax convenience you're looking for.
LESS might be useful:
#AdminUser {
& .admin-label-margin {
margin-left: 160px;
/* ... */
}
/* ... */
}
There is no way to simplify it in CSS.
You could use a CSS preprocessor language, such as SASS, which would allow you to:
#AdminUser {
.admin-label-margin {
margin-left:160px;
margin-top:-25px;
padding-bottom:10px
}
#entitytitle h4 {
margin-left:175px;
padding-bottom:13px
}
input[type='text'] {
width:180px
}
.admin-label-span {
margin-left:-15px!important;
margin-right:12px
}
}