How to add CSS if element has more than one child? - html

I have td tags and a several div inside td:
<td>
<div class='test'></div>
<div class='test'></div>
</td>
<td>
<div class='test'></div>
</td>
I want to add margin-bottom to div if there are more than one in the td. How can I do this with the css?

You can't directly 'count' total numbers of elements in CSS, so there's no way to only apply the class if there's 2 or more divs (you'd need JavaScript for that).
But a possible workaround is to apply the class to all divs in the td...
td > div {
margin-bottom: 10px;
}
... and then override/disable it with a different style when there's only one element. That indirectly lets you add the style when there's 2+ more child elements.
td > div:only-child {
margin-bottom: 0px;
}
Alternatively you can apply to every div after the first one, if that happens to work for your situation.
td > div:not(:first-child) {
margin-bottom: 10px;
}
Edit: Or as Itay says in the comment, use a sibling selector
td > div + div {
margin-bottom: 10px;
}

td > div:not(:only-child) { margin-bottom: 10px; }

Well actually you can do this with css using the nth-last-child selector
FIDDLE
So if your markup was like this:
<table>
<td>
<div class='test'>test</div>
<div class='test'>test</div>
</td>
</table>
<hr />
<table>
<td>
<div class='test'>test</div>
</td>
</table>
CSS
div:nth-last-child(n+2) ~ div:last-child{
margin-bottom: 40px;
}
... the above css will style the last div element only if there exists a container that has at least 2 child divs
Just to see how this works better - here's another example fiddle

did a nice little combo with the accepted answer
only applies style to the first child when its NOT the only child.. so when there is more than 1
td > div:not(:only-child):first-child { }

CSS-Has has limited browser support:
but here you go:
td:not(:has(div:first-child:last-child))
bonus:
td:not(:has(div:only-child))

i think there is no way to add the 10px margin to each div inside a td without the use of css3.
so a solution would be to use javascript and check if there are more than 1 div's inside the td and then if yes add a special class.
css
.myMarginClass div{
margin-bottom:10px;
}
js
var td=document.getElementsByTagName('td'),
l=td.length;
while(l--){
if(td[l].getElementsByTagName('div').length>1){
td[l].className='myMarginClass';
}
}
else for modern browsers the proper solution is the :only-child
proposed by #mikel

If there are other kinds of elements inside the td, you can still select the only div with this :only-of-type
<td>
<div class='test'></div>
<div class='test'></div>
</td>
<td>
<div class='test'></div>
<p class='test'></p>
</td>
CSS
td > div:only-of-type{
margin-bottom:10px;
}

Related

Regarding showing a button when you hover over HTML table row

I have created an HTML table, with one column dedicated to a button that's invisible by default. When you hover over a row, I have the corresponding button become visible. This all works fine, and here's an example of the HTML and CSS.
HTML:
<table>
<tr>
<td></td>
<td></td>
<td><button class="btn btn-danger btn-sm hidden-button">Delete</button></td>
</tr>
</table>
CSS:
.hidden-button {
opacity:0;
}
td:hover .hidden-button {
opacity:1;
}
My question though, is why does this work? I was experimenting, but completely expected all of the buttons with class .hidden-button to become visible. Could someone take a second and explain to me why this is not the case? Thank you!
td:hover .hidden-button applies your opacity: 1; to elements with the hidden-button class nested under each given td that is in the hover state.
your below CSS code applying globally on all TD
td:hover .hidden-button {
opacity:1;
}
td:hover .hidden-button actually refers to only the hidden-button which is present inside the td over which your mouse is hovering. So only this one element will appear when your mouse hovers over the td element.
In CSS, you come to the class of parent to child by reading the code from left to right.
The reason this works is because your specifically targeting ALL td elements inside of your html, so whenever you hover over a td, you target that td element of all td elements inside of the table.
.box {
height:100px;
width:100px;
background-color:black;
margin:10px;
float:left
}
.box:hover {
background-color:red
}
<div class="box box1">1</div>
<div class="box box2">2</div>

display table cell none in style tag

I might be missing something really obvious, however consider the following code (tested in Edge and Chrome):
<head>
<style>
.table td { display:table-cell; }
.hide { display: none; }
</style>
</head>
<body>
<table class="table">
<tr>
<td class="hide">This is supposed to be hidden</td>
</tr>
</table>
</body>
Here is a JSFiddle demo as well.
Why is the <td> child ignoring the display:none?
Now, I know that, for example, removing the .table class or in-lining <td style="display:none"> will get me the desired outcome (hiding the cell).
I'm interested in understanding the logic of this behivour.
Why is the child ignoring the display:none?
Because .table td is more specific as .hide. You ran into a concept called css specifitiy.
Take a look here: https://specificity.keegan.st
The actual reason is,
You can't add both the display:table-cell; and display: none; to the same DOM property.
In this case, you're giving two different values for the same property where CSS gives the importance to the display:table-cell;
Check out the another answer given here which speaks about 'CSS Specificity'.
Two ways to overcome this issue.
One is adding the !important tag for the style which you want to apply that is a bad practice.
Another solution is adding visibility: hidden which will hide the element from the view.
It's because .table td { display:table-cell; } is the closest css selector to the td than .hide { display: none; } so you can solve this by adding td.hide { display:none; }

Child style overriden by parent style CSS (different issues)

Sorry.. I'm just a little bit confused with other answer in SO..
I have 2 tables,
and one of them rendered inside a table. (table in table)
<table class="master">
<tr>
<td>ID</td><td>Name</td><td>Information</td>
</tr>
<tr>
<td>1</td>
<td>John</td>
<td>
<table class="detail">
<tr>
<td>ID</td><td>Order</td>
</tr>
<tr>
<td>1</td><td>CA09-WYOMING-BR</td>
</tr>
</table>
</td>
</tr>
</table>
style
<style>
table.detail{
border:1px solid red;
border-collapse: collapse;
/* etc...about 20 lines code */
}
table.detail td{
border:1px solid red;
background:red;
/* etc...about 20 lines code */
}
table.master {
border:1px solid black;
border-collapse: collapse;
}
table.master td {
border:1px solid black;
background:gray;
}
</style>
And the detail table style not rendered properly because overridden by parent table CSS.
I know there are !important tag to make child CSS style not overridden, but if the CSS style about 20 lines of code should I add '!important' tag to all of them?
?
http://jsfiddle.net/vxdM3/
No need for !important here... Reverse the order of your styles. Put the css for the master table before detail. The way you have it is that the css for detail is being applied first then the master css is applied overriding what was set for detailed.
re-orded css fiddle
Or if you don't want to move css around you can update the selectors to table.master table.detail{} and table.master table.detail td{}.
updated selector fiddle
As a general rule, I use > to avoid styling nested elements unintentionally.
.master > tr > td
{
....
}
Actually, since I always use tbody, it is more like:
.master > tbody > tr > td
I don't like surprises, so I try to be careful to write css that is very explicit on what it is styling. Sure, it is a bit slower, but I find it is insignificant to the user experience and I can get stuff done a lot quicker. Others may do it differently, of course.

CSS positioning of two horizontal elements

How do I align foo to left and bar link to right?
<td>
<span>foo</span>
<span>bar</span>
</td>
You should use float to achieve that
Demo
td span:first-of-type {
float: left;
}
td span:last-of-type {
float: right;
}
Note that the pseudo I am using will target the first and the last span respectively, but if you are looking to support legacy versions of IE or other browsers, this will fail, using unique class for each span is recommended instead.
The only reason am using pseudo here is it saves me to declare classes, this is a huge advantage if you want to do this for each td
Also, I assume that you are not well informed for float or you must have tried to do so, if that's the case, you can refer my answer here for detailed information over float and also refer this, which isn't necessary for this scenario because you are using float in td except the floated elements, but if you have any elements or text apart from these two elements in the same td than make sure you clear the floating elements.
td > span:first-child {
float: left;
}
td > span:last-child {
float: right;
}
DEMO: http://jsfiddle.net/Px4un/
You can use inline styles, like this:
<td>
<span style="float: left;">foo</span>
<span style="float: right">bar</span>
</td>
Or plain CSS:
<style>
.left {
float: left;
}
.right {
float: right;
}
</style>
<td>
<span class="left">foo</span>
<span class="right">bar</span>
</td>
Please, don't use pseudo elements, like :first-child or :first-of-type, because it will be not cross-browser.

Class in TR without one TD

<table>
<tr class="here"><td><input type="text" readonly=readonly></td></tr>
<tr class="here"><td><input type="text" readonly=readonly></td></tr>
<tr class="here"><td><input type="text" ></td></tr>
</table>
td {
padding: 15px;
margin: 10px;
}
.here {
background-color: red;
}
http://jsfiddle.net/dZYEM/
How can i modify class .here that this working where child input has attribute readonly? I dont want modify html.
EDIT:
now i have: jsfiddle.net/dZYEM/2/
i would like receive: http://jsfiddle.net/dZYEM/3/
but without use style. I want receive this only with css.
There is no pure CSS way to do this as CSS does not have a has or contains selector.
But this can be done using one line of jQuery. And it's really fast.
$("tr.here:has(input[readonly='readonly'])").css('background', 'red');
Here is a working jsFiddle to try it - http://jsfiddle.net/T7hnR/2/
Hey you have two option
first is if your tr is last than apply this css
tr:last-child{
background:none;
}
Second is if your tr number is 3 than used to it.
tr:nth-of-type(3){
background:none;
}
Like here : http://jsfiddle.net/dZYEM/10/
CSS:
tr:nth-child(3n) {
background: none !important;
}
One could edit the inner element by makiung use of CSS2 selectors
E[foo="warning"] Matches any E element whose "foo" attribute value is exactly equal to "warning".
But this will not allow you to select the outer parent element.
Under either CSS2 or CSS3 this does not exist, and you would have to do it with the solutions provided with JavaScript/jQuery.