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.
Related
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.
Please is possible to set scss for element inside --rounded ? I do not wanna use .box__something, but I need to modify children that is depend on parent modifier
<div class="box">
<div class="box__something">Hello</div>
</div>
<div class="box box--rounded">
<div class="box__something">Hi</div>
</div>
.box {
&__something {
background: blue;
}
&--rounded {
background: green;
.box__something { // <<< Is some better selector?
background: pink;
}
}
}
Sass doesn't have any great built-in solutions to solve your issue, this is a problem that has been explored many times. You can however acheive the result you are after in a slightly un-elegant manner by using the & helper to join the classes that you wish to join. I have included a live example here.
While this does work, you must realise that if you want to style the .box--rounded class directly you must have it inside it's own class as illustrated below, you cannot use it with the trailing & class that we have placed &__something on.
I recommend you play around with my sassmeister gist and see what results you can come up with.
.box {
&__something {
background: blue;
}
&--rounded {
background: green;
}
&--rounded & {
&__something {
background: pink;
}
}
}
I hope this has solved your issue.
The modifier should be used not on the parent, and the child element .box__something
If I understand your problem correctly, I feel your pain! As soon as you nest a nested property & changes to the parent.
You can however cache the original class name as a variable like this:
$box: box;
.#{$box} {
.#{$box}__something {
background: blue;
}
.#{$box}--rounded {
background: green;
.#{$box}__something { // <<< Is some better selector?
background: pink;
}
}
}
The only problem with the method above is that you end up with a larger volume of compiled CSS. This renders to:
.box .box__something {
background: blue;
}
.box .box--rounded {
background: green;
}
.box .box--rounded .box__something {
background: pink;
}
To reduce the size of the output you could combine & with the variable method like so:
.box {
$box: &;
&__something {
background: blue;
}
&--rounded {
background: green;
#{$box}__something {
background: pink;
}
}
}
This renders to:
.box__something {
background: blue;
}
.box--rounded {
background: green;
}
.box--rounded .box__something {
background: pink;
}
That way you can change the class name in the variable and everything gets updated, I also think it reads a bit better.
Let me explain:
I have multiple items with all different width's. And when I hover them it displays captions at 50% width. BUT the captions on the images at 25% are way too small.
I want to make the captions 100% width and 100% height on the ones with 25%.
Can I specify this in my css?
List of images:
.item1 {
width:100%;
float:left;
}
.item2 {
width:25%;
margin-left:50%;
margin-right:25%;
float:left;
}
.item3 {
width:50%;
margin-right:25%;
float:left;
}
.item4 {
width:25%;
float:left;
}
.item5 {
width:50%;
margin-left:50%;
float:left;
}
.item6 {
width:50%;
margin-right: 50%;
float:left;
}
posthover = my selector
.posthover {
width:50%;
height:auto;
display:none;
#post:hover .posthover {
display:block;
It must be something like this:
.posthover (only width 25%) {
width:100%
height:100%
}
#post:hover .posthover (only width 25%) {
width:100%
height:100%
}
Specify your own width and height in pixels
.hover:hover {
width: 100px;
height: 100px;
}
So you want to set the height and width to 100% only on the items that use 25%, right?
Then declare that.
.item2 {
width:25%;
margin-left:50%;
margin-right:25%;
float:left;
}
.item2:hover {
width:100%;
}
Can you use a css rule as a selector?
No, as great as this would be, we cannot select via CSS properties.
Here are two ways to limit your selection
Using this HTML
<ul>
<li class="item1"></li>
<li class="item2"></li><!-- Select this -->
<li class="item3"></li>
<li class="item4"></li><!-- Select this as well -->
<li class="item5"></li>
<li class="item6"></li>
</ul>
#1 - Select the awesome way:
Browser Compatibility: Browser support is pretty good (IE 9 +)
If you need broader browser support, use the second, boring example.
Use nth-child:
li:hover:nth-child(2n):nth-child(-n+4) {
width:100%;
}
Let's break down the parts:
li:hover = on li hover
:nth-child(2n) = select every second li
:nth-child(-n+4) = select only from the first four lis
Become an nth master!
Awesome Example
Hover the list item blocks
* {
margin: 0;
padding: 0;
}
li {
background: #F00;
height: 100px;
transition: all 0.3s;
}
.item1 {
width: 100%;
}
.item2 {
width: 25%;
}
.item3 {
width: 50%;
}
.item4 {
width: 25%;
}
.item5 {
width: 50%;
}
.item6 {
width: 50%;
}
li:hover:nth-child(2n):nth-child(-n+4) {
width: 100%;
}
<ul>
<li class="item1"></li>
<li class="item2"></li><!-- Select this-->
<li class="item3"></li>
<li class="item4"></li><!-- Select this as well -->
<li class="item5"></li>
<li class="item6"></li>
</ul>
#2 - Select The boring way
String the class selectors together with ,
.item2:hover,
.item4:hover {
width:100%;
}
Browser Compatibility: Everywhere.
Boring Example
Hover the list item blocks
* {
margin: 0;
padding: 0;
}
li {
background: #F00;
height: 100px;
transition: all 0.3s;
}
.item1 {
width: 100%;
}
.item2 {
width: 25%;
}
.item3 {
width: 50%;
}
.item4 {
width: 25%;
}
.item5 {
width: 50%;
}
.item6 {
width: 50%;
}
.item2:hover,
.item4:hover {
width: 100%;
}
<ul>
<li class="item1"></li>
<li class="item2"></li><!-- Select this -->
<li class="item3"></li>
<li class="item4"></li><!-- Select this as well -->
<li class="item5"></li>
<li class="item6"></li>
</ul>
No, there is nothing even remotely resembling the use of a CSS rule as a selector. The same applies to what you are actually asking in the question body, namely using the value of a property (somehow) in a selector. A CSS style sheet is a collection of rules that are independent of each other; they interact only in the sense that they all (potentionally) contribute to the way in which elements are rendered.
Thus, you need to analyze how your style sheets set, say, the width of something to 25% and then use the selectors in the rules identified to set up additional rules.
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
}
}
I have some rules nested inside each other, and I'd like to add another unrelated element to one of the rules.
For example if I have
#element1{
display: block;
.sub-element1 {
background: yellow;
.sub-element2 {
color: red;
}
}
}
and then I'd like to add another element (#element2) to use same rules as .sub-element2, so compiled code would look like this:
#element1{
display:block
}
#element1 .sub-element1 {
background:yellow
}
#element1. sub-element1 .sub-element2, #element2 {
color: red;
}
Is it possible?
You could use a mixin. You can add rules to a mixin, then include the mixins where you want them:
#mixin redcolor {
color:red;
}
Then simply include this mixin in any selector:
.subelement2, #element2 {
#include redcolor;
}
More on mixins here:
http://sass-lang.com/guide
Use #extend.
#element2 {
#extend .sub-element2
}
The output created by this will however also copy the selector chain, so this would be the output:
#element1. sub-element1 .sub-element2, #element2 {
color: red;
}
Perhaps that is what you want, but I can imagine it's not.
In this case you'll need to write an #extend only selector. It works much like an #include, except it generates the compact output you outline in your question. You could do it many ways, this is one of them:
%red {
color: red;
}
#element1{
display: block;
.sub-element1 {
background: yellow;
.sub-element2 {
#extend %red;
}
}
}
#element2 {
#extend %red;
}
Here's a link to it in the official docs.