setting padding depending on number of child elements - css

I have a DIV element which may contain 1 or 2 Child DIVs
Is there a way to say of there is 1 Child element then the padding should be 15px otherwise 5px
It may like
<div class="container">
<div><strike>7.00</strike></div>
<div>5.00</div>
</div>
or
<div class="container">
<div>7.00</div>
</div>

You can do a trick using margin in the children to get the same effect:
.container div:only-child {
margin: 15px;
}
div {
border: solid 1px red;
}
div div {
margin: 0 5px;
border-color: green;
background: #ccc;
}
div div:first-child {
margin-top: 5px
}
div div:last-child {
margin-bottom: 5px
}
<div class="container">
<div><del>7.00</del></div>
<div>5.00</div>
</div>
<div class="container">
<div>7.00</div>
</div>
PS Use del tag instead strike that is deprecated

No, there is not.
CSS does have some complex quantity queries but these will only style the children based on their number.
It is not (currently) possible to style the parent based on the number of children as there is no Parent Selector

Based on how old this original thread is I'm not providing exact solutions, however, CSS Tricks put a great article together covering Logical CSS styling. You can find the article here.

Related

Changing CSS Property From an Array using JS

I am currently building a todo app, and from react, I am using CSS to custom my todo items' margin!
The problem is, I only needed the first element to have a margin-top of 110px. Here's what it'll look like when I apply it to every item - link
It's that the todolist items are too separated!
But if I removed the margin of 110px, the item is behind the textbox!
link
Is there a way to change the property of first item? I can delete the margin-top: 110px from the css file, and change the 1st item using JS. My planned function -
function addTodo() {
setList([...list, value]);
const firstItem = list.findIndex(0);
}
Thanks!
:first-of-type selector in CSS allows you to target the first occurence of an element within its container. Also, another option might be to select first child of the element, you can use :first-child pseudo-class.
There are several possibilities to solve this problem. I think the simplest one is to just build a container that contains all list items, and set it's padding-top or margin-top to 110px. The result could look like this:
.frame {
margin-left: auto;
margin-right: auto;
padding: 10px;
width: 200px;
border: 1px solid #000;
text-align: center;
}
.control-button {
position: absolute;
}
/* this is the container that holds all your items */
.items-container {
margin-top: 40px; /* in your case, it should be 110px */
}
.item {
margin-top: 10px;
border: 1px solid #000;
}
<html>
<body>
<div class="frame">
<div class="control-button">
<u>add item</u>
</div>
<!-- this is the important part, the container with the items -->
<div class="items-container">
<div class="item">
This is an item.
</div>
<div class="item">
This is another item.
</div>
</div>
</div>
</body>
</html>
I think this solution is the most simple and flexible one. You can easily add left, right or bottom margins too and you don't have to worry about which items it affects.
The simplest solution you can go with is using the :nth-child(n) pseudo class in CSS or :first-of-type.
Try this code:
.item:nth-child(1) {
margin-top: 110px;
}

First-of-type selector applies to all children of a parent

Here is my HTML and CSS:
.wrapper > p:first-of-type {
margin-bottom: 20px;
}
<div class="wrapper">
<p>...</p>
<p>...</p>
</div>
However, the margin property is being applied to both elements. What's wrong?
It is not applied to the first element only, but the second element was not applied to it
And even if applied to it you did not notice that because the margin is down and the last element
There are two extra rules you can put into your CSS that will show you that your first-of-type selector is working correctly. Firstly, you can add
* {
margin: 0
}
Most browsers, by default, add a margin-top and margin-bottom to all <p> elements. If you do not explicitly eliminate this, sometimes called a CSS reset, it will always be used. getting rid of it allows you to see that only your top <p> element has a margin on the bottom.
If you still have trouble seeing this, you can add
p {
border: 1px solid green
}
Having a border will show you more clearly that the top paragraph has a margin and the bottom one does not. Add a third <p> for the result to stand out more starkly.
* {
margin: 0
}
.wrapper > p:first-of-type {
margin-bottom: 20px;
}
p {
border: 1px solid green
}
<div class="wrapper">
<p>...</p>
<p>...</p>
<p>...</p>
</div>

Can I principally style the parent element based on child element using CSS3?

An Example: Only DIVs, that containing a LABEL should get the style text-align: right
Following try did not work:
div label:only-child {
text-align: right;
}
Not the label but the div should get this style.
you can use this way
div class="test" style="text-align:left"
div class="test" style="text-align:right"
The solution is to set the width of the label and display property to block. Here's the code
div{
width: 500px;
padding: 20px;
background: #fff;
border: 1px solid #ddd;
}
div>label:only-child{
text-align: right;
width: 100%;
display: block;
}
<div>
<label>adfasdf</label>
</div>
this cannot be done with CSS .
CSS = Cascading Style Sheets so by definition you can select elements from top to bottom of the HTML structure, not the other way around.
so you can't select a parent depending on it's children
you can do this with JQ , there are a number of ways to do it but this would be one of them :
$( "div:has(label)" ).css({ "text-align":"right" });
.div {
height:50px;
border:2px solid red;
margin:2px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="div">
<label>Has Label</label>
</div>
<div class="div">
<p>
i am NOT a label
</p>
</div>
<div class="div">
<label>Has Label</label>
</div>
You can't style parent element based on child element using CSS.
Since, it seems that you are trying to align the label element to right, you can do that using float as shown below:
div label:only-child {
float: right; /* instead of text-align: right */
}
Updated (parent has flexbox layout):
div label:only-child {
flex: auto;
text-align: right;
}
You cant't do this in CSS only. Well, of course you can add class to div but there is no parent selector.
But there will be in the future (selectors lvl4 - see last row of selectors overview): https://www.w3.org/TR/selectors4/

Center Div Tags in another Div Tag

I'm trying to get a parent div tag to hold n children div tags such that they are all on the same line, yet grouped together in the center. For example:
Here the children are blue, and the parent is red.
Here are the things I've tried:
Making blue divs display:inline to get them on the same line. Problems: doesn't display even with its width and height both set to 10px.I tried adding , but it only was a couple pixels wide.
Making blue divs float:left. Problems: Have to programmatically resize red parent to child contents since the divs are floated and then center in its parent to get what I want. There should be a solution that doesn't involve javascript.
For IE6 and IE7 compatibility you might have to add zoom:1; and *display:inline; to your child CSS
jsFiddle
.parent {width:100%;border:1px solid red;text-align:center;}
.child {width:15%;display:inline-block;border:1px solid blue;}
<style>
.container {
width: 100%;
padding: 0;
text-align: center;
border: 1px solid red;
}
.inner {
display: inline-block;
margin: 0 5px;
border: 1px solid blue;
}
</style>
<div class="container">
<div class="inner">
one
</div>
<div class="inner">
two
</div>
<div class="inner">
three
</div>
</div>
Stick the blue divs in a container div. Find their widths (margin and padding included) and give the container div that width. Then set the container div's margin to 0 auto, stick it in the red div and you should be fine.
Try to use display: inline-block;:
.child {
display: inline-block;
...
}
http://jsfiddle.net/mupuR/

CSS first GENERATION div but not second selector

I want to match the first generation division elements (all of them) but NOT any of THEIR children. So if I used the selector to apply a border 1 (as below visually) would gain the container however 2 (as below visually) would NOT gain the container. How do I construct that selector please?
<div id="container">
<div>1<div>2</div></div>
<div>1<div>2</div></div>
<div>1<div>2</div></div>
</div>
#container > div {
border: 1px solid #f0f;
}
The best way is using the immediate child selector (>):
#container > div {
border: 1px solid red;
}
(IE6 does not support this)
The selector for that is:
div#container > div
or just
#container > div
I really like the SelectORacle to help understand CSS selectors. More on Child Selectors from Eric Meyer.
UPDATE FOR Microsoft Internet Explorer 6
If support for > is a concern, as in the case of MSIE6, the traditional way I used to handle it was to set the styles for the first generation, then unset them for every other descendent generation. So, like this:
#container div { border: 1px solid #000; }
#container div div { border: none; }
#container div div div { border: none; }
#container div div div div { border: none; }
You do that with as many generations down as you need to do. In the above I allow 3 more levels of nesting (enough?) It is not pretty, but it is reliable.
Since one browser in particular (IE6) does not support the child selector >, you could use descendent selectors instead to add a border to the first descendant and remove it from the descendent's descendent.
HTML
<div id="container">
<div>1
<div>2</div>
</div>
<div>1
<div>2</div>
</div>
<div>1
<div>2</div>
</div>
</div>
CSS
#container div {
border:1px dashed grey;
}
#container div div {
border:none;
}
If IE6 is a browser you do need to support then the > selector as already answered is the simplest way to style the child.

Resources