Bracket CSS Selector - css

Looking around for responsive web design and I came up with a piece of code which also exists in the Bootstrap framework.
Can someone please explain what the actual code does
#media only screen and (max-width: 768px) {
/* For mobile phones: */
[class*='col-'] {
width: 100%;
}
}
Could not find the selector in this site which has a lot of selectors as examples

[class*='col-']
is the so-called attribute selector. The basic form is e.g. this:
[type='checkbox']
which would select all elements on a page that have an attribute type that equals checkbox.
The basic form can be modified using certain prefix characters:
[class*='col-']
matches all elements which have a class in their classlist whose name contains (*=) col-.
The same exists for starts with:
[class^='col-']
and for ends with:
[class$='col-']
https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors
Combined with the media query, what that full rule does is make any container element that is defined as a Bootstrap column have the full width (and no longer be a column) instead (which is usually what you want on mobile devices like smartphones).

This complex selector in css but it is simple indeed.
Infact this is so usefull.
In following example there are four divs and there is CSS selector which checking if there is any of the divs having test in their class, then it selects them and apply properties on them.
div[class*="test"] {
background: #ffff00;
}
<div class="first_test">The first div.</div>
<div class="second">The second div.</div>
<div class="test">The third div.</div>
<p class="test">This is some text.</p>

This CSS means: For screen only, for a viewport maximum width of 768px and below, for all elements with a class containing col-; set their width to 100%.

Related

Weighted or relative ordering of flexbox items

As I understand, the flexbox css property order is absolute, i.e. the last element in a flex container with order: 0 raises to the top.
I'd like to be able to promote certain elements in a flex container so they won't raise to the exact place but instead by a number of elements, e.g. move the element above the previous one.
To clarify:
<div>A</div>
<div>B</div>
<div>C</div>
<div style="order: -1">This should go up by one, between B and C</div>
That style will of course move the last element to the top and not where I want it to be.
Is there a way to achieve this with just css?
Apparently I'm asking the impossible. Since I'll likely be needing this kind of ordering at some point, I'll just have to make an ordering system in javascript that changes the children's order property on the fly. I have it kind of figured out, but not clearly enough to put in words right now.
I guess it's worth mentioning that this is for a layout editor that will be exporting plain html and css. Javascript will only be used in the editor and not the published site. Otherwise it would be enough to just reorder the actual elements, but at some points certain elements need to be prioritized for different devices.
I'll eventually answer this question with the method I come up with but in the meantime feel free to add your own suggestions and grab the points for accepted answer :)
Here's a CSS-only solution, using CSS's var() and calc().
Codepen
Step 1: Give all items an explicit index
When we render the list, we make sure to explicitly set an index per item in the list (otherwise they default to '0' if none set). We use a CSS var for that because it's more easily accessible within CSS calc; otherwise we'd may want to use attr() which is more of an option if you do JS logic).
<div id="wrapper">
<!-- Each item has an explicit CSS var defined -->
<div style="--data-myIndex:0;">A</div>
<div style="--data-myIndex:1;">B</div>
<div style="--data-myIndex:2;">C</div>
<div style="--data-myIndex:3;">D</div>
<div style="--data-myIndex:4;">E</div>
<div style="--data-myIndex:5;">F</div>
<div style="--data-myIndex:6;">G</div>
</div>
<style>
#wrapper > * {
margin: 1em;
padding: 1em;
background-color: #EEEEEE;
/* We set the order based on the CSS var myIndex (set in HTML) */
order: var(--data-myIndex);
}
</style>
Step 2: Shift an item relatively
With all items having an explicit index, we can then shift a specific item in a relative way (e.g. +/- x) using our index value within calc().
<style>
#media(max-width: 768px) {
/* Shift a specific element (e.g. 3rd) by some number (e.g. 2); we use the index inside calc to do a relative shift! */
#wrapper div:nth-child(3) {
order: calc(var(--data-myIndex) + 2);
background-color: #AAAAAA;
}
}
</style>
In this use case, I'm doing it at a breakpoint. In mobile view, we shift a particular item by a relative amount. It's only possible because everything has an explicit index.
You could also do this shift in JS if you prefer. If using JS, you could use a data attribute on elements as opposed to CSS var.

How to select the ID that's before another ID [duplicate]

This question already has answers here:
Is there a "previous sibling" selector?
(30 answers)
Closed 8 years ago.
I'm trying to do a CSS selection.
I want to select an ID that's before another ID selector.
This is the example:
<div id="wrapper">
<div class="aside_left">Left content...</div>
<div class="main_page">Main content...</div>
</div> <!-- end of wrapper -->
My objective is that the main_page stay on the left, and the aside_left change its position to the right.
Both the aside_left and the main_page have the property float:left I can't change the aside_left property to float:right because it is in many pages.
Is it possible to select the ID or CLASS that is before another ID?
My selector should be something like this: select the .aside_left that are before an .main_page
You cant do this with CSS selectors per se.. your best bet is to use something like jQuery's very accessible .parent() method.
You can see here for CSS3 and here for CSS2, this is not present in the current spec.
The speculative design for CSS4 does provide such a selector using a ! operator, but is not presently supported in any browser.
With this in mind, perhaps think about changing the logic behind what you're trying to do- can you not give the altered elements different class names to more easily identify them? Or progress down from your wrapper element?
Or, have a look into the nth-of-type selector, by using:
#wrapper .aside_left:nth-of-type(odd)
See THIS FIDDLE
This will select only the .aside_left elements which are the first child of the #wrapper element. The first child, as in the first in the DOM, as opposed to the first displayed (using float may visually produce results that dont reflect actual DOM positioning in which case you're back to using jQuery).
Only if HTML Structure Cooperates is Pure CSS Possible
I noted in my comment and ExtPro has noted in his answer that such is not possible by pure css, at least under most conditions. However, there is one set of conditions that it is possible. That is if there end up being more child elements of #wrapper in the html when something other than .main_page is present. This would be a very specifc case requirement, and may not match your situation (probably not based off your comment to ExtPro), but if so, then this code works:
#wrapper > .aside_left:nth-last-of-type(2) {
float: right;
}
See an example fiddle here. You see how this requires that there be two elements only in the case that the .main_page is there, and would demand more elements be present if .main_page is not there. So this technically does not key in on .main_page itself, but rather is using the html structure to change a preceding element based off the number of sibling elements present.
in pure CSS you could use display:flex and order , despite position in the flow of .main_page : (hover it to see them both switching sides).
/* using your HTML */
#wrapper {
display: flex;
flex-flow: row wrap;
height:200px;
width:80%;
margin:auto;
}
#wrapper > div {
width:20%;
box-shadow:inset 0 0 1px;
order:2;
}
#wrapper .main_page {
width:80%;
}
#wrapper > div.aside_left {
background:gray;
}
#wrapper > div.main_page:hover {
order:1;
}
live démo at http://codepen.io/gc-nomade/pen/Iywbj see some tips to use it here : http://css-tricks.com/snippets/css/a-guide-to-flexbox/
You could as well reset direction on #wrapper if you style your 2 div as inl'ne-boxes and restore direction on the childs divs

Order of CSS selectors

Take a look at this example, simple enough:
http://jsfiddle.net/8YuKb/
Now look at this example:
http://jsfiddle.net/n223Z/1/
The ONLY difference between the two is the line
.text_left { text-align:left; }
is moved above the following line:
.title {
margin:4px;padding:6px;
background-color:black;color:white;
font-size:12pt;font-weight:bold;
text-align:center;
}
... and now the CSS does not work??? (at least not in IE)
Can someone please explain why???
I was under the impression that because the "text_left" selector was last in the list the text in the div should be aligned left (regardless of the order of CSS declarations) -- is that not the case????
I do not understand why it works in one case and not the other.
As you can see, the order of the classes in the HTML has no effect.
Both of the following are the same, as they are merely elements with 2 of the same classes.
class="title text_left"
class="text_left title"
On the other hand, the order of the elements does matter in CSS, as the stylesheet is read from top to bottom (cascade).
Thus text-align:left is being applied on both elements, yet due to the order in which they appear, it is overwritten by text-align:center, as it appears below it.
1.in html
class="title text_left"
class="text_left title"
has the same effect when they apply to the same element: the class sequence they appear in
html attribute has no effect in the final result
2.in css file:
.title {}
.text_left {}
when the two class apply to a element such as
<div class="title text_left"></div>
or
<div class="text_left title"></div>
the html has the same effect(as describe in 1), so the div will apply all rules in .title
and .text_left. if the same style has declared in both .title and .text_left. the rule
in .text_left will win (the one declared last in css file win when their selector has the
same specificity)
3.in css file
.text_left {}
.title {}
when an element has both the two classes, all style rule in the two class will apply to
the element, if two attrbute conflict, .title will win
maybe you mixed the word: the one declare last will win
it means: the sequence of css rule declare in source file effect the final result
not: the sequence of attribute declare in html element

nth-child(odd) not working as expected

Why does every row have a red background when I'm using nth-child(odd)?
<div id="ClientTable">
<div class="ClientTableHeaderRow"><span class="ClientTableHeaderColumn">Full Name</span></div>
<div class="ClientTableRow"><span class="ClientName">Umpa Beeson</span></div>
<div class="ClientTableRow"><span class="ClientName">Umpa Beeson</span></div>
<div class="ClientTableRow"><span class="ClientName">Umpa Beeson</span></div>
<div class="ClientTableRow"><span class="ClientName">Umpa Beeson</span></div>
</div>​
#ClientTable {position: relative;
display: table;
margin-top: 20px;
width: 100%;}
#ClientTable:nth-child(odd) {background-color:#FF0000;}
.ClientTableHeaderRow, .ClientTableRow {display: table-row; }
.ClientTableHeaderRow {font-weight: bold;}
.ClientTableHeaderRow span, .ClientTableRow span {display: table-cell;}​
View the jsFiddle
The expected result is every other row to be red. Instead, as you can see, every row is red.
P.S. Umpa is my cat.
You should be setting ClientTableRow class, like so:
.ClientTableRow:nth-child(odd) {background-color:#FF0000;}
Demo: http://jsfiddle.net/gMR2K/4/
EDIT
As also explained by animuson, you need to apply the :nth-childselector to the element itself, not the parent. The name of the selector can lead one to think it will apply the styling to the children of the selected element, when actually the style is applied to n-th child of the selected element, across the whole document.
Also, if you're worried about browser compatibility you can also do this with JavaScript. Here's an example using jQuery.
$(document).ready()
{
$(".ClientTableRow:nth-child(odd)").addClass("redBackground");
}
Demo: http://jsfiddle.net/gMR2K/10/
As stated here by BoltClock: jQuery "polyfills the :nth-child() selector for older browsers anyway."
nth-child applies to the actual element, not its children. #ClientTable is the 1st (and only) child of its parent. Therefore, it has a red background. You need to be applying the nth-child to the elements inside that division.
Is this the result you want?:
http://jsfiddle.net/gMR2K/6/
#ClientTable div:nth-child(odd) {background-color:#FF0000;}
and that only works in the better browsers. IE 8 and below don't get it. But, you can use jQuery to make it work everywhere or (painfully) add a class to the odd rows.
In my case I made a small mistake
.someclassA .someclassB: nth-child(odd){
You can see as above there is one space between someclassB: and nth-child. thats it.. By deleting that space it started working :)

CSS :last-child

I have a div#content with many div.item inside it.
When using :last-child to make the last div.item with no border-bottom, it's OK.
But, as the content is dynamically appended using php and mysql results I'm using a conditional pagination table that will be appended after the last div.item which means at the bottom of the div#content. Here will be the problem as the CSS :last-child will not recognize the last div.item as the last-child.
my CSS looks like:
div#content div.item:last-child {
border-bottom: none;
}
as you can see I'm defining that the last child id such a div.item
Any suggestions please. thanks in advance.
!!!!! Please note that the problem is not in the fact that the content is dynamic but in the fact that the CSS :last-child doesn't recognize the div.item as the last child but the last element in the div#content despite telling the CSS that it's:
div#content div.item:last-child
One possibility I can think of is that you're appending elements that aren't <div>s and/or don't have the item class. Check the output of your PHP/MySQL script and see if there are any non-div.item elements beside (in DOM terms) the div.item elements.
Such elements will not match the selector:
div#content div.item:last-child
That selector finds only <div>s with item class, that are the last child of div#content.
Here's an example.
Before appending
<div id="content">
<div class="item"></div> <!-- [1] Selected -->
</div>
After appending
<div id="content">
<div class="item"></div> <!-- [2] Not selected -->
<div></div> <!-- [3] Not selected -->
</div>
What's being selected, what's not, and why?
Selected
This <div> element has the item class, and it's the last child of div#content.
It exactly matches the above selector.
Not selected
This <div> element has the item class, but is not the last child of div#content.
It doesn't exactly match the above selector; however, it can possibly match either one of these selectors:
/* Any div.item inside div#content */
div#content div.item
/* The last div.item child of its parent only */
div#content div.item:last-of-type
Not selected
Although this <div> element is the last child, it does not have the item class.
It doesn't exactly match the above selector; however, it can possibly match this:
/* Any div that happens to be the last child of its parent */
div#content div:last-child
It seems appending items dinamically does not make the layout engine re-run some CSS rules like :last-child.
I think you can re-read/reload CSS file making the rule apply. Don't know, it's a guess.
Another possibility is dinamically set the styles.
EDIT: It seems you have a CSS x Browser problem.
Check this out: http://en.wikipedia.org/wiki/Comparison_of_layout_engines_%28Cascading_Style_Sheets%29#Selectors
you could use javascript to refresh the CSS only. See here: http://paulirish.com/2008/how-to-iterate-quickly-when-debugging-css/
Another approach would be to use a library like jQuery and fire this line of script every time you add new divs. (or maybe you're using another js library, as you say that you are dynamically adding divs to the page)
$('div#content div.item:last-child').css('borderBottom','none');
you might need to reset borders before you do the above though. i.e. the previous 'last' div may still not have the border bottom. so reset all borders then fire the script to remove the border for the last one.

Resources