CSS Selecting First Child - css

Im still trying to figure out how to properly use my nth, first, and last child selectors. Thanks for your patience.
If my markup is like this:
<div class="the-wrapper">
<table class="the-table">
<!-- the table -->
</table>
<table class="the-table">
<!-- the table -->
</table>
</div>
How can I select the last <table class="the-table"> to apply a margin?
I thought I could select it like this: .the-wrapper .the-table:last-child { /* css */ } but this does not work. What am I missing? Thank you!
EDIT
Sorry everyone I printed my markup incorrectly... The correct markup is above

The + is used to select "siblings" elements. (siblings in the sense of being childs of the same parent) http://jsfiddle.net/Lhmjq/
You can't use nth-child or last-child for this; as the name say, is for childs, and unless you put a parent, you can't do it.
Here is an example with a parent: http://jsfiddle.net/Lhmjq/2/ In this case, is done with last-child
(updated to your new code)
Here is a tiddle: http://jsfiddle.net/Lhmjq/4/
.the-wrapper .the-table:last-child {
color: blue;
}
Updated with your new code: http://jsfiddle.net/Lhmjq/4/

.the-wrapper .the-table:last-child { /* css */ }
The previous code should select the last table in the wrapper. The targeting for structural pseudo classes can be confusing. The pseudo classes are defined in regards to it's direct parent. For instance, say you have a list of elements:
<ul class="target-me">
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
and you want to target the last li in the list. Your CSS would be:
.target-me > li:last-child { color: red; }
You can also use the pseudo selectors to target numbered items from the position in the DOM, say I want to target the second element:
.target-me > li:nth-child(2) { color: red; }
You can also use these pseudo selectors in a selector hierarchy.
.target-me > li:first-child span { ... }
You can also chain pseudo selectors:
.target-me > li:first-child:hover { ... }
In conjunction with a polyfill like Selectivizr you can use these selectors on all browsers. I hope this helps!

Your code ".the-wrapper .the-table:last-child " will return the last-child elements of ALL your ".the-wrapper" classes. What you want to do is select the last ".the-wrapper" element. The code below will select the last-child table of the last ".the-wrapper" element, which is what you are looking for...
$('.the-wrapper .the-table:last-child').last().css("border","1px solid #b5b5b5")
Cheers!

Related

Cursor change on hover

I am trying to change the cursor on hover when mouse cursor hovers over a table. The view here is written in ruby-rails. I tried simply adding
.custom > table:hover·
{
cursor: wait;
}
adding the above to custom.css.scss
And then I added the below code to my view
<table class="nav nav-tabs custom">
This does not seem to work.
I know the css code has to be within some block but I am not sure of the exact way of going about it especially within ruby on rails. Any way to correct what I am doing wrong?
EDIT:
Thanks for the suggestions.
I tried this
table.custom:hover{
cursor:wait;
}
although this works in the table header it does not work for the part where the data within the table is being rendered:
<table style="display:none" class="nav nav-tabs custom">
<%= render ClassName.new, :index => 'N_TYPE' %>
</table>
And rendering columns similar to this
<td><%= label_tag :p_type, p_type.p_type %></td>
.custom > table:hover·
{
cursor: wait;
}
What your CSS does is it looks for a children table inside a selector with class .custom. So it wont work for your HTML.
The proper way is
table.custom:hover{
cursor:wait;
}
which looks for a table with the class name .custom and applies CSS
Fiddle
In your style you have made use of the child combinator ">". Child combinator is used to apply CSS to child elements of the selected element.
For eg.
HTML:
<ul>
<li>First</li>
<li>Second</li>
</ul>
CSS:
ul > li {
width: 100px;
}
will apply style on both "li" as they both are child of "ul".
In your case you need to apply css on direct element. For that purpose you don't need to use child combinator.
Also you are making of CSS Pseudo classes. This classes can be directly apply to element.
Eg.
#mycustomid:hover
.mycustomclass:hover
elementname:hover
Check attached jsfiddle code.
http://jsfiddle.net/zgjx7ymr/
There is no child table elements under the class custom. Try like this.
table.custom:hover
{
cursor:wait;
}

set only the css style of first adjacent div with a class name

How can I set the style of only the first div that has class "bla"? (not the second).
<div class="outer">
<div>
....(more div's, unknown how many)
<div class="bla">
....
<div class="bla">some content</div>
</div>
....
</div>
</div>
I'm assuming with this answer that by adjacent elements you mean sibling elements. If you were referring to parent-child elements then go with N1xx1's answer. That being said...
You can't target the first bla with css selectors alone. But you can target all the blas but the first. So, one possibility is to set the styles you want only on the first bla on all blas. Then override those styles by targeting all blas but the first. Like so:
.bla {
...styles for the first bla..
}
.bla ~ .bla {
...override styles set on first bla that you dont want on the others
}
The tilde between the two ".bla"'s is called the general sibling selector. If you've never heard of it, head on over to css selectors spec.
You can do simple workaround for this since you can't do that with any special selector:
.bla {
/* style here, example: */
background-color: #f00;
}
.bla .bla {
/* negate the style, example: */
background-color: transparent;
}
I hope this is what you were looking for.
According to pure css, you can't select according to the ordering of the html elements. Search the spec (here: http://www.w3.org/TR/CSS2/selector.html). There is nothing that refers to how many or in what order html elements match the given selectors.
Javascript:
getElementsByClass('bla')[0].style
EDIT: JOPLOmacedo provided a CSS only (better) answer
I've also found a way to select for instance the second <p> after a <h1> tag:
h1 + p + p{
background: red;
}
Just thought I'd share that.

Is it possible to chain :not() then :last-child?

I need to style (CSS only) the last child element while excluding those with a specific class.
For example, I want to style
<ul>
<li>Bar</li>
<li>Bar</li>
<li>Bar</li>
<li>Should have a green background</li>
<li class='foo'>Bar</li>
</ul>
The last li without class 'foo' should be green. I tried
li:not(.foo):last-child {
background-color: green;
}​
or
li:not(.foo):last-of-type {
background-color: green;
}​
but it doesn't works.
See http://jsfiddle.net/gentooboontoo/V7rab/2/
The answer to your question Is it possible to chain :not() then :last-child? (or, more simply, can pseudo-classes be chained?) is very much a yes. But as others have pointed out, if an li:last-child has an id="foo" then nothing will be selected. As a demonstration, a similar expression
li:not(.bar):last-child {
background-color: green;
}​
works just fine. The problem is that successive selectors all apply to the entire context, not to a subset specified by previous expressions so li:not(.foo):last-child is identical to li:last-child:not(.foo), which is clearly not what is required.
I don't think that will work (it doesn't work, but I don't think it should work anyway)
The selector is working, but the second-to-last li is never going to be the :last-child because it isn't the last-child...
It isn't like jQuery's not() method which actually removes the specified element from the selection. The CSS :not selector/filter will ignore the element, but not remove it from the page
There is only one last child inside any element. In your example, it's <li class='foo'>Bar</li>. If you have exact number of children though, you could use adjacent-sibling combinator:
LI:first-child + LI + LI + LI {/* here are declarations for 4th LI. */}
Applying 'last-child' will give browser issue. so I tried in Jquery.
If you need use this code.
var a = 0
$('ul li').each(function() {
$(this).attr("id",a);
a++;
});
var b = a-1;
$('#'+b).attr('style','background-color:green');​

style 2nd element on the page with same class

Hello is there a way with css to style the 2nd element on page with the same class slightly differently to the first.
For example I have two ul's on a page with a class of topbardropdownmenu. I want to give the 2nd ul a differen't background to the first. Is there a way to do this with out altering the html?
You can do it with the :nth-child() pseudo-selector. It is CSS3 though, and not supported in some browsers (e.g. <=IE8 & <=FF3.0 doesnt support it).
.topbardropdownmenu:nth-child(2) { background: #FF0000; }
You could do it with JavaScript in a cross-browser compatible way though, if that's an option for you.
What holds the <ul> elements? I'll assume a <div id = "lists">
/* First element */
div > ul.topbardropdownmenu:first-child{
}
/* Rest of the elements */
div > ul.topbardropdownmenu{
}
...alternatively
div > ul.topbardropdownmenu:not(:first-child)
It depends which browsers your users are using, you might be able to use the nth-of-type css pseudo-selector:
ul.topbardropdownmenu:nth-of-type(2) {
/* styles the second ul of class=topbardropdownmenu
}
If there's a particular pattern to the occurrence of these ul elements, you could use descendant and/or sibling selectors:
div > ul.topbardropdownmenu {
/* styles all ul.topbardropdownmenu that are the immediate descendants of a div */
}
p + ul.topbardropdownmenu {
/* styles all ul.topbardropdownmenu that immediately follow a p */
}
Look at the CSS3 nth-child() pseudo-class.
You can use :nth-child http://css-tricks.com/how-nth-child-works/ but IE may struggle with it. Consider this jQuery alternative:
$(".class").eq(1).css();
http://api.jquery.com/eq/

css or html5 for first and last elements

Users can enter descriptions which may include paragraphs or lists. Or they may just enter text without any enclosing <p> or <ul> elements. What I need to do is remove most of the padding and margin above the first element and below the last element so that the user entered content has a nice tight border around it. So I could do one of the following:
Use a css rule I was unaware of to target only the first and last elements
Use css3 or html5 (I assume there's something within these to easily do what I want) and hope everyone upgrades their browsers asap while the older browsers just get a slightly uglier version of the page
Find the first and last elements with Javascript and modify accordingly
Modify the html to add a class like <p class="first">
Ideally the 1st solution exists, does it? I'm ok with the 2nd solution though if not, does it exist? The last 2 I don't care for...
UPDATE: don't care about IE6. But I do need to deal with the situation that if there's just text to begin with, without any <p> or <ul> or other elements, then actually nothing special needs to be done for the top margin/padding.
Use :first-child and :last-child like this. Note that > and :first-child (CSS2) doesn't work in IE6 and below, and :last-child (CSS3) doesn't work in IE8 and below. The only real workaround to both is to use a .first and .last class respectively (you can add them dynamically with JavaScript as Phrogz says).
.description > p, .description > ul {
margin: 1.5em 0;
}
.description > :first-child {
margin-top: 0;
}
.description > :last-child {
margin-bottom: 0;
}
I added the > combinator to prevent elements like strong or li getting selected. What does it mean?
Something like this?
.container * + p, .container * + ul
{
margin: 1em 0 0;
}
.container p, .container ul
{
margin: 0;
}
BoltClock's answer works great in most cases, but IE8 and earlier ignores the :...-child pseudo-selectors.
You can use jQuery to accomplish the same thing, while targetting more browsers.
//On ready...
$(function(){
//Update styles dynamically
$('ul:last').css({'margin-bottom':0,'padding-bottom':0});
$('ul:first').css({'margin-top':0,'padding-top':0});
});
Have you considered wrapping the content in a container with a negative margin? It requires the content to at least be wrapped in a single p element (not hard to test/add melodramatically).
CSS:
.container {border:1px solid black;}
.container .subcontainer {margin:-1em 0;}
.container p {margin:1em 0;}
HTML:
<div class="container"><div class="subcontainer">
<p>My first paragraph.</p>
<p>My second paragraph.</p>
</div></div>

Resources