CSS - parent element overrides child element properties - css

The problem is very simple:
<div id="main-content">
<ul>
<li>
<div class="post-row">
<div class="post-footer">
This is the Footer
<div class="footer-buttons">
<ul>
<li>Edit</li>
<li>Reply</li>
</ul>
</div>
</div>
</div>
</li>
</ul>
</div>
And now main content:
#main-content ul {
margin:0;
padding:0;
}
#main-content ul li {
display:block;
list-style:none;
}
And last, footer-buttons:
.footer-buttons {
float:right;
}
.footer-buttons ul {
margin:0;
padding:0;
}
.footer-buttons ul li {
display: inline;
}
The problem is that the list in .footer-buttons is displayed as block. And in fact when I checked DOM the display: inline is overrided by the #main-content.
From what I know understrand this shouldn't happen. Or am I wrong and id elements will always override child classes?

You have 2 selectors: #main-content ul li and .footer-buttons ul li . First of them uses id and the second uses class, that's why the first one is used as more descriptive. Use:
#main-content .footer-buttons ul li { display: inline; }

I think IDs do take priority over classes however this post may have more info
CSS class priorities
you could always add !important on the .footer-buttons ul and ul li declarations or add the id in front of th3e .footer-buttons class
e.g.
#main-content .footer-buttons ul

Yes, selectors with IDs will always override selectors with just classes. This is due to "specificity"; you can get a good overview here.
Solutions here would include adding #main-content to your footer selectors, or declaring the style as display: inline !important;.

Maybe I misunderstand your question, but if you want the actual list to be inline, this should work:
.footer-buttons ul {
margin:0;
padding:0;
display: inline;
}
What your code does is make the list elements be displayed as inline.

This is correct behaviour because an id is considered more specific than a class, and so to use them in a similar scenario will always give the id rule priority.
The best way to fix this is by defining more specific rules. This doesn't have to mean targeting everything by class though, you can build your rules from the specific ids, like is TommyB's answer. !important should however be avoided: What are the implications of using "!important" in CSS?

Keep in mind that IDs have higher priority than classes, and inline style is higher than IDs. The best fix would be to refactor your css, removing display:block; from #main-content. Or even better: make main-content a class. Avoid using !important, it's not a good practice.

Related

Styling nested UL with same class

I have a nested list and I'm having trouble styling the last level UL.
<ul class="same-class">
<li>
<ul class="same-class">
<li>
</li>
</ul>
</li>
</ul>
What I need is to display the first UL items inline, and below them show their children as blocks. The problem is both UL have the same class (I can't change the HTML output, nor add classes), and I can't find the proper selector to target the second UL.
In the example here I tried adding a diferent class to menu 3 and 4, and that does the trick, but since changing class isn't an option I need to find a workaround to make the children display as blocks.
Can someone take a look and advise?
ul ul li { display: block; } or .same-class .same-class li { display: block; } should do the trick - that'll select all li that are a child of two or more ul or .same-class
This might be useful (attribute selectors) depending on what your real code looks like (most likely useful if you're using AngularJS or something similar) or the nth-child might be good too because I'm not 100% sure what you mean.
Hope this helps!
If you try plugging this in, you should be able to target the various components as you like.
The first selector is targeting all list items that are direct children of the first menu.
The second one is targeting any lists inside of a list item which itself is a direct decendant of the menu class.
The third one is targeting just your list items in your nested lists. It gives a good degree of control for adjusting the layout.
ul.menu:first-of-type > li{
display:inline-block;
}
.menu > li ul {
display:block;
}
.menu:first-of-type > li > ul > li {
display:block;
}
If you was to use CSS parent selectors then try;
ul.same-class li {
display: inline-block;
}
li > ul.same-class li {
display: block;
}
The > in the second rule will select all ul.same-class li elements where it has a li as a parent.

Using CSS inline on one list

I am trying to apply my CSS file to 2 of my lists
<ul class="list1">
<li>Cat</li>
<li>kittens</li>
</ul>
<ul class="list2">
<li>Pizza</li>
<li>Popcorn</li>
</ul>
I want only one of them to be inline so I'm trying
ul.list1 {
display: inline;
}
but the inline won't work unless I do
li {
display: inline;
}
which applies to all my lists. How do I make it son only inline affects one list?
I'm guessing you want one of the lists to be horizontal, like so:
.list1 li { display: inline; }
Look up how to use descendant selectors, it is one of the basic powers of CSS.
Increase the specificity of your selector. For example...
ul.list1 li { display: inline; }
For further complexity as an example... If you have both of these lists appearing twice in your site, once inside a div with the ID #content, and once inside a footer widget with ID #widget. Then you can target the list inside #content by typing.
#content ul.list1 li { display: inline; }
Here is a link to an article to the W3C Wiki on CSS3 Selectors
The above link will give you everything you need to know concerning combinators, pseudo-selectors and pseduo-elements. Learn this and you can conquer the internet.
Use
.list1 li {display:inline;}
The following code will make all of your listings inline, as I can understand, this is not your intention.
li {
display: inline;
}
Instead, you should specify that you only want one of the lists elements to have this style. You should therefor use the following code.
.list1 li {
display: inline;
}
This will make all list entries within the list1 class inline.

How to add styles based on whether top element is empty

How do you change styles of another element based on whether the first element is empty.
<ul></ul>
<ul>
<li>....</li>
<li>....</li>
<li>....</li>
</ul>
In the above code, I want to give a style for the second ul { color:red } (to be more exact the ul that follows) ONLY if the first ul is empty.
Is there a pure CSS solution for this?
You can do this, but only if the element in question is completely empty- yes, not even a whitespace.
http://jsfiddle.net/NicoO/uTJ4N/
ul:empty + ul
{
color: red;
}
To be more accurate, this is the selector you need for the first empty <ul> of the body and the exact following <ul>:
body > ul:first-of-type:empty + ul
{
color: red;
}
http://jsfiddle.net/NicoO/uTJ4N/1/
Try this code:
ul > li {
color: red;
}
Its selects the ul which has a li as child element. And those can be colored red then.
http://jsfiddle.net/keypaul/KfaQv/1/
ul:not(:empty) {
color:red;
}
I dont think a pure css solution is the way to go, but you can use a pre-processor as they allow you to pass conditional statements.

Why isn't the CSS ID the highest priority CSS rule in this case?

I have built a CSS navigation header, and it's working exactly the way I want in regards to positioning, stylization, all that. This is the CSS that stylizes it:
#header ul {
padding:72px 0 0 0;
text-align:center;
}
#header ul, #header ul li {
margin:0;
list-style:none;
}
#header ul li {
display:inline;
}
#header ul li a {
font-size:17px; color:#69C; text-decoration:none;
display:inline-block;
height:44px;
line-height:44px;
margin:3px 6px;
padding:0 26px;
}
#header ul li a:hover {
background:#69C;
color:#FFF;
}
And this is the list:
<div id="#header">
<ul>
<li>HOME</li>
<li>WHAT WE DO</li>
<li>ABOUT US</li>
<li>GET STARTED TODAY!</li>
</ul>
</div>
Pretty simple stuff (and currently viewable at http://www.pmind.com/staging, but I included the code here for potential future readers).
You may notice in the list, the final li has an ID assigned to it. When I add this rule to the CSS:
#get_started {
color:#3C0;
}
Nothing happens. It was my understanding that A. CSS rules that come later in the CSS document have priority over rules that come earlier, and B. CSS rules used with the ID selector had the highest priority no matter what. But clearly the blue colourization that comes from the earlier CSS rules is still taking priority over colouring the final li green. I tried to make sure I did my due diligence Googling for the solution, but everything I find says that IDs get the highest priority (and this has also been my understanding in practice for everything I've coded before this one issue).
If you were trying to override a selector that didn't have an ID with one that did, your confusion would be spot on.
In this case, though, you're using #get_started (which has an ID) to override #header ul li a which also has an ID in it.
Surely you're thinking that your ID is more specific than the #header ID — and you're not entirely wrong — but that's not how CSS works. It only cares about the number of IDs used in the selector, not which elements those IDs happen to target.
To figure out which of two selectors takes precedence, first count the IDs in each. If one has more IDs than the other, it wins and you're done.
If it's the same number (in this case both have one) move on to the number of classes. Again, if one has more classes than the other, it wins and you're done. In this case, both have zero classes.
So we move on to the number of tag names. Once again, if one has more tag names it wins. And here #header ul li a has three tags in it (ul, li, and a) whereas #get_started has none. You lose. The existing selector wins.
You could work around this with just #header #get_started which now has two IDs, but my preference would be to more clearly describe it as:
#header ul li a#get_started
#header ul li a has a higher specificity than #get_started
You should read the w3c specs on specificity.
EDIT to add:
Just remember that although specificity is commonly written in short-hand as powers of 10, 10 elements will never be more specific than one class, and 10 classes will never be more specific than one id.
E.X.
html body div table tbody tr td ul li a is less specific than .some-link-class
Checkout the excellent video:
Understanding CSS Specificity
can you try this
#get_started {
color:#3C0!important; // this will take the priority
}
Did you try?
#get_started:link {
color:#3C0;
}

Can I override a #id ul li behaviour with a class definition

I have an area that is identified by a #id and there is a CSS like:
#id ul li {
margin:0;
}
can I, for a specific UL in that area, override the margin-setting? I understand that #id creates very high priority in evaluating the formatting.
I have tried:
.myclass ul li {
margin-left: 20px;
}
and
#id ul.myclass {
as well as
#id li.myclass {
Is it even possible?
I agree with SWilk, avoid !important if possible (and it is possible here). Some other solutions that SWilk did not offer is:
#id ul.myclass li {
or...
#id ul li.myclass {
The key is increasing the specificity of the selector, which the above, and SWilk's solutions do. The reason your original solutions did not work is that you did not include the other tag (ul or li) nor the #id with your addition of the .myclass.
Added after your comment that showed structure:
If your html is this (as you stated in your comment):
<div id="ja-col2">
<div>....
<ul class="latestnews">
<li class="latestnews">
And your current css is (as stated in another comment):
#ja-col1 ul li,
#ja-col2 ul li {
margin:0; padding-left:15px;
}
#ja-col2 .latestnews ul li, /*does not exist*/
.latestnews #ja-col2 ul li, /*does not exist*/
.latestnews ul li, /*does not exist*/
ul.latestnews li.latestnews {
list-style:disc outside url("../images/bullet.gif");
margin-left:15px; padding-left:15px;
}
ul li { line-height:180%; margin-left:30px; }
The reason you are not seeing any change is because three of your selector paths do not exist in your html structure, and the one that wins by specificity is the very first group. You need:
#ja-col2 ul.latestnews li
To override the #ja-col2 ul li.
.myclass ul li {
margin-left: 20px !important;
}
Should do the trick :)
Use pseudo fake :not ID
.myclass:not(#f) ul li {
margin-left: 20px;
}
#hello .hello-in{
color:red;
}
.hello-in:not(#f){
color:blue;
}
<div id="hello">
<div class="hello-in">
Hello I am red
</div>
</div>
you can even use :not(#♥) or any html4/5 ( depends on page type ) character
Avoid using !important. This is hard to debug and is very probable, that it will interfere with other selectors. Especially if you will try to change css in few months from now, when you will forget there was an !important clause in some place.
You need to put more specific selector than the previous one. Just use the class and id parts in one selector.
Try using either
#id .myclass ul li {
margin-left: 20px;
}
or
.myclass #id ul li {
margin-left: 20px;
}
depending on where the element with "myclass" class is located in the DOM tree - if it is the parent of the #id element use first example, otherwise the second.
If you want to be independent of the #id element, try to use:
#id .myclass ul li,
.myclass #id ul li,
.myclass ul li {
margin-left: 20px;
}
This will work for all li's inside ul inside .myclass element, and it will not matter whether there is any #id element in the tree.
Best regards,
SWilk
http://www.w3.org/TR/WCAG10-CSS-TECHS/#user-override
In order to ensure that users can control styles, CSS2 changes the semantics of the "!important" operator defined in CSS1. In CSS1, authors always had final say over styles. In CSS2, if a user's style sheet contains "!important", it takes precedence over any applicable rule in an author's style sheet. This is an important feature to users who require or must avoid certain color combinations or contrasts, users who require large fonts, etc. For instance, the following rule specifies a large font size for paragraph text and would override an author rule of equal weight:
P { font-size: 24pt ! important }

Resources