CSS :last-child unexpected behaviour [duplicate] - css

This question already has answers here:
Can I combine :nth-child() or :nth-of-type() with an arbitrary selector?
(8 answers)
Closed 7 years ago.
Hi I am trying to use the last-child operator to hide the last div which applies a border. My issue is that the las div still has the border on the bottom
Below is the HTML for my Test
<div class="car-search">
<!--other divs removed for example-->
<div class="border-bottom"></div>
</div>
<div class="car-search">
<!--other divs removed for example-->
<div class="border-bottom"></div>
</div>
The CSS
.car-search .border-bottom{
border-bottom: 1px solid $lighterGrey;
padding-top: 15px;
margin-bottom: 15px;
width: 770px;
margin-left: 15px;
}
.car-search:last-child .border-bottom{
display: none;
}
I have no idea why the border is being displayed on the last .car-search
Current Output:
.car-search .border-bottom {
border-bottom: 1px solid #000;
padding-top: 15px;
margin-bottom: 15px;
width: calc(100% - 30px);
margin-left: 15px;
}
.car-search:last-child .border-bottom {
display: none;
}
Attempts
I have also tried using the !important tag with no success
I have tried :last-of-type with no success

Unfortunately there is no last-of-class selector inside of CSS. You'll either need to remove the .border-bottom element from your last .car-search element, or fall back to Javascript / jQuery to remove the element from the DOM.
For example, you could run the following jQuery code to remove the last .car-search element's .border-bottom:
$('.car-search').last().children('.border-bottom').remove();
jsFiddle Demo
Alternatively, if you wish to use pure CSS for this, you could wrap your .car-search elements inside of a container <div> and use the :last-of-type selector.
For example, your new structure might look like:
<div class="car-search-wrapper">
<div class="car-search">
<!--other divs removed for example-->
<div class="border-bottom"></div>
</div>
<div class="car-search">
<!--other divs removed for example-->
<div class="border-bottom"></div>
</div>
</div>
Then you may use:
.car-search:last-of-type .border-bottom {
display: none;
}
jsFiddle Demo

As said above there is no :last-of-class selector for now so the only way to do it is javascript. With jQuery you can run the following code:
jQuery('div.car-search:last .border-bottom').css({display:'none'});
Moreover with scss you can write
.car-search {
.border-bottom {
border-bottom: 1px solid $lighterGrey;
padding-top: 15px;
margin-bottom: 15px;
width: calc(100% - 30px);
margin-left: 15px;
}
&:last-of-type {
.border-bottom {
display: none;
}
}
}
Which is a bit less of scss lines.
In compiled CSS:
.car-search .border-bottom {
border-bottom: 1px solid $lighterGrey;
padding-top: 15px;
margin-bottom: 15px;
width: calc(100% - 30px);
margin-left: 15px;
}
.car-search:last-of-type .border-bottom {
display: none;
}

Related

Using flex and flex-wrap with borders [duplicate]

Say I have two divs next to each other (take https://chrome.google.com/webstore/category/home as reference) with a border.
Is there a way (preferably a CSS trick) to prevent my divs from appearing like having a double border? Have a look at this image to better understand what I mean:
You can see that where the two divs meet, it appears like they have a double border.
If we're talking about elements that cannot be guaranteed to appear in any particular order (maybe 3 elements in one row, followed by a row with 2 elements, etc.), you want something that can be placed on every element in the collection. This solution should cover that:
.collection {
/* these styles are optional here, you might not need/want them */
margin-top: -1px;
margin-left: -1px;
}
.collection .child {
outline: 1px solid; /* use instead of border */
margin-top: 1px;
margin-left: 1px;
}
Note that outline doesn't work in older browsers (IE7 and earlier).
Alternately, you can stick with the borders and use negative margins:
.collection .child {
margin-top: -1px;
margin-left: -1px;
}
#divNumberOne { border-right: 0; }
HTML:
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
​CSS:
div {
border: 1px solid #000;
float: left;
}
div:nth-child(n+2) {
margin-left: -1px;
}
Demo
Include ie9.js for IE8 support (it's very useful for all CSS selectors/pseudo-elements).
Another solution one might consider is using the CSS Adjacent sibling selector.
The CSS
div {
border: 1px solid black;
}
div + div {
border-left: 0;
}
jsFiddle
I'm late to the show but try using the outline property, like so:
.item {
outline: 1px solid black;
}
Outlines in CSS do not occupy physical space and will therefore overlap to prevent a double border.
You can use odd selector to achieve this
.child{
width:50%;
float:left;
box-sizing:border-box;
text-align:center;
padding:10px;
border:1px solid black;
border-bottom:none;
}
.child:nth-child(odd){
border-right:none;
}
.child:nth-last-child(2),
.child:nth-last-child(2) ~ .child{
border-bottom:1px solid black
}
<div>
<div class="child" >1</div>
<div class="child" >2</div>
<div class="child" >3</div>
<div class="child" >4</div>
<div class="child" >5</div>
<div class="child" >6</div>
<div class="child" >7</div>
<div class="child" >8</div>
</div>
If the divs all have the same class name:
div.things {
border: 1px solid black;
border-left: none;
}
div.things:first-child {
border-right: 1px solid black;
}
There's a JSFiddle demo here.
Add the following CSS to the div on the right:
position: relative;
left: -1px; /* your border-width times -1 */
Or just remove one of the borders.
Using Flexbox it was necessary to add a second child container to properly get the outlines to overlap one another...
<div class="grid__container">
<div class="grid__item">
<div class="grid__item-outline">
<!-- content -->
</div>
</div>
</div>
SCSS
.grid__container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 0 1px 0 0; // margin-right 1px to give the correct width to the container
}
.grid__item {
flex: 0 1 25%; // grid of 4
margin: 0 0 1px; // margin-bottom to prevent double lines
}
.grid__item-outline {
margin: 0 0 0 1px; // margin-left to prevent double lines
outline: 1px solid #dedede;
}
If you also need to change border colors on interaction (eg. swatch selector in a form), I found out a nice trick to do it, using a combination of negative margins, padding adjustment and transform translate. Check it out:
.parent{
display: flex;
width: 100%;
max-width: 375px;
margin-left:1px;
}
.child {
margin-left: -1px;/* hide double borders behind their siblings */
flex: 1 0 auto;
}
.child input {
display:none
}
.child label {
display:block;
border: 1px solid #eaeaea;
min-height: 45px;
line-height: 45px;
cursor: pointer;
padding: 0 10px; /* will be changed when input is checked */
font-size: 15px;
text-align: center;
}
.child input:checked+label {
border: 1px solid red;
transform: translateX(-1px);
padding-left: 11px;
padding-right: 9px;
background-color: #fafafa;
}
<div class="parent">
<div class="child">
<input id="swatch-1" type="radio" value="1" name="option" checked="true">
<label for="swatch-1">Element 1</label>
</div>
<div class="child">
<input id="swatch-2" type="radio" value="2" name="option">
<label for="swatch-2">Element 2</label>
</div>
<div class="child">
<input id="swatch-3" type="radio" value="3" name="option">
<label for="swatch-3">Element 3</label>
</div>
</div>
My use case was for boxes in a single row where I knew what the last element would be.
.boxes {
border: solid 1px black // this could be whatever border you need
border-right: none;
}
.furthest-right-box {
border-right: solid 1px black !important;
}
<div class="one"></div>
<div class="two"></div>
<div class="two"></div>
<div class="two"></div>
<div class="two"></div>
CSS:
.one{
width:100px;
height:100px;
border:thin red solid;
float:left;
}
.two{
width:100px;
height:100px;
border-style: solid solid solid none;
border-color:red;
border-width:1px;
float:left;
}
jsFiddle
​
I just use
border-collapse: collapse;
in the parent element
I know this is a late reaction, but I just wanted to drop my 2 cents worth, since my way of doing it is not in here.
You see, I really don't like playing with margins, especially negative margins. Every browser seems to handle these just that tad bit different and margins are easily influenced by a lot of situations.
My way of making sure I have a nice table with divs, is creating a good html structure first, then apply the css.
Example of how I do it:
<div class="tableWrap">
<div class="tableRow tableHeaders">
<div class="tableCell first">header1</div>
<div class="tableCell">header2</div>
<div class="tableCell">header3</div>
<div class="tableCell last">header4</div>
</div>
<div class="tableRow">
<div class="tableCell first">stuff</div>
<div class="tableCell">stuff</div>
<div class="tableCell">stuff</div>
<div class="tableCell last">stuff</div>
</div>
</div>
Now, for the css, I simply use the rows structure to make sure the borders are only where they need to be, causing no margins;
.tableWrap {
display: table;
}
.tableRow {
display: table-row;
}
.tableWrap .tableRow:first-child .tableCell {
border-top: 1px solid #777777;
}
.tableCell {
display: table-cell;
border: 1px solid #777777;
border-left: 0;
border-top: 0;
padding: 5px;
}
.tableRow .tableCell:first-child {
border-left: 1px solid #777777;
}
Et voila, a perfect table.
Now, obviously this would cause your DIVs to have 1px differences in widths (specifically the first one), but for me, that has never created any issue of any kind. If it does in your situation, I guess you'd be more dependant on margins then.
I was able to achieve it using this code:
td.highlight {
outline: 1px solid yellow !important;
box-shadow: inset 0px 0px 0px 3px yellow;
border-bottom: 1px solid transparent !important;
}
A very old question, but it was the first google result, so for anyone that comes across this and doesn't want to have media queries to re-add the border to the right/left of the element on mobile etc.
The solution I use is:
.element {
border: 1px solid black;
box-shadow: 0 0 0 1px black;
}
This works because you'll see a 2px border around the element made of the border and the shadow. However, where the elements meet, the shadow overlaps which keeps it 2px wide;
To add to a 9 year old question, another clean and responsive way to achieve this is to:
Add a border-left and border-top to the parent
Add border-right and border-bottom to each of the children
What about giving a margin:1px; around your div.
<html>
<style>
.brd{width:100px;height:100px;background:#c0c0c0;border:1px solid red;float:left;margin:1px;}
</style>
<body>
<div class="brd"></div>
<div class="brd"></div>
<div class="brd"></div>
</body>
</html>
DEMO
I prefer to use another div behind them as background and delete all the borders. You need just to calculate the size of the background div and the position of the foreground divs.

Get rid from the text indentation [duplicate]

This question already has answers here:
How to remove the space between inline/inline-block elements?
(41 answers)
Closed 4 years ago.
How could I get rid from the text indentation in my case?
html:
<div class="mainContainer">
<div class="promptTitle">
Module Name
</div>
<div class="drawRegion">
</div>
<div class="nameTitle">
Module Name
</div>
</div>
css:
.mainContainer {
border: 1px darkgray solid;
border-radius: 10px;
}
.promptTitle {
color: #b8b8b8;
padding-top: 25px;
padding-left: 70px;
}
.drawRegion {
display: inline-block;
width: 50px;
margin-right: 0;
}
.nameTitle {
display: inline-block;
padding-left: 20px;
}
jsfiddle:
https://jsfiddle.net/76uedo40/561/
problem on screenshot:
My problem is that the second line of text Module Name is displayed with an indentation. I would expect to not have the indentation.
That is because the first Module Name indented 70px from left, while the second Module Name indented 50px from left due to the element with class="drawRegion" and 20px due to its own left padding. So, in total both first and second Module Name should indent 70px. And hence both should be placed with the same indentation, but this is not the case.
So, what am I missing here or what am I doing wrong?
Try removing the spacing between the drawRegion & nameTitle inline-block divs.
.mainContainer {
border: 1px darkgray solid;
border-radius: 10px;
}
.promptTitle {
color: #b8b8b8;
padding-top: 25px;
padding-left: 70px;
}
.drawRegion {
display: inline-block;
width: 50px;
margin-right: 0;
}
.nameTitle {
display: inline-block;
padding-left: 20px;
}
<div class="mainContainer">
<div class="promptTitle">Module Name</div>
<div class="drawRegion"></div><div class="nameTitle">Module Name</div>
</div>
Check this answer for a good explanation of white space between inline & inline-block elements.
There's no point in making the nameTitle as inline-block as you display the elements as blocks.
Therefore, keep the same CSS styles for the first and the last element.
.nameTitle {
display: block;
padding-left: 70px;
}

CSS padding not working properly?

I think i have a issue with the padding.
I made a simple box with only just a padding: 20px; and for me it looks like the padding-bottom is more than 20px.
Here are some screenshots:
Here is my simple css:
.panel {
width: auto;
height: auto;
border-radius: 2px;
margin-bottom: 20px;
position: relative;
}
.panel-default {
padding: 20px;
border: 1px solid #e0e0e0;
background: #fff;
}
.panel-default > .panel-body {
font-size: 14px;
}
HTML:
<div class="grid_4">
<div class="panel panel-default">
<div class="panel-body">Lorem ipsum dolor sit amet.</div>
</div>
</div>
I use 960 Grid System, but i dont think this happend because of this.
And i have in my html, body {} the box-sizing set up to border-box and the line-height to 24px.
Hope someone can help me :)
The padding is alright, the problem is with your margin-bottom: 20px;.
This should be your .css:
.panel {
width: auto;
height: auto;
border-radius: 2px;
position: relative;
}
.panel-default {
padding: 20px;
border: 1px solid #e0e0e0;
background: #fff;
}
.panel-default > .panel-body {
font-size: 14px;
}
This code will have the effect you are looking for.
https://jsfiddle.net/r67nxyL5/
Either you have a margin somewhere.You can check this by inspecting the element using your internet browser (right click).
or you can try floating your .panel-default and giving it a display block like so:
.panel-default {
float: left;
display: block;
}
if this doesn't work it's definitely a margin-bottom somewhere :)
Perhaps you didn't remove the default margin from the paragraph tag, which adds up to the bottom.
Try to set up paragraph margins to 0.

Using two CSS classes on one element

What am I doing wrong here?
I have a .social div, but on the first one I want zero padding on the top, and on the second one I want no bottom border.
I have attempted to create classes for this first and last but I think I've got it wrong somewhere:
.social {
width: 330px;
height: 75px;
float: right;
text-align: left;
padding: 10px 0;
border-bottom: dotted 1px #6d6d6d;
}
.social .first{padding-top:0;}
.social .last{border:0;}
And the HTML
<div class="social" class="first">
<div class="socialIcon"><img src="images/facebook.png" alt="Facebook" /></div>
<div class="socialText">Find me on Facebook</div>
</div>
I'm guessing it's not possible to have two different classes? If so how can I do this?
If you want two classes on one element, do it this way:
<div class="social first"></div>
Reference it in css like so:
.social.first {}
Example:
https://jsfiddle.net/tybro0103/covbtpaq/
You can try this:
HTML
<div class="social">
<div class="socialIcon"><img src="images/facebook.png" alt="Facebook" /></div>
<div class="socialText">Find me on Facebook</div>
</div>
CSS CODE
.social {
width:330px;
height:75px;
float:right;
text-align:left;
padding:10px 0;
border-bottom:dotted 1px #6d6d6d;
}
.social .socialIcon{
padding-top:0;
}
.social .socialText{
border:0;
}
To add multiple class in the same element you can use the following format:
<div class="class1 class2 class3"></div>
DEMO
Remember that you can apply multiple classes to an element by separating each class with a space within its class attribute. For example:
<img class="class1 class2">
If you have 2 classes i.e. .indent and .font, class="indent font" works.
You dont have to have a .indent.font{} in css.
You can have the classes separate in css and still call both just using the class="class1 class2" in the html. You just need a space between one or more class names.
If you only have two items, you can do this:
.social {
width: 330px;
height: 75px;
float: right;
text-align: left;
padding: 10px 0;
border: none;
}
.social:first-child {
padding-top:0;
border-bottom: dotted 1px #6d6d6d;
}
I know this post is getting outdated, but here's what they asked.
In your style sheet:
.social {
width: 330px;
height: 75px;
float: right;
text-align: left;
padding: 10px 0;
border-bottom: dotted 1px #6d6d6d;
}
[class~="first"] {
padding-top:0;
}
[class~="last"] {
border:0;
}
But it may be a bad way to use selectors. Also, if you need multiple "first" extension, you'll have to be sure to set different name, or to refine your selector.
[class="social first"] {...}
I hope this will help someone, it can be pretty handy in some situation.
For exemple, if you have a tiny piece of css that has to be linked to many different components, and you don't want to write a hundred time the same code.
div.myClass1 {font-weight:bold;}
div.myClass2 {font-style:italic;}
...
div.myClassN {text-shadow:silver 1px 1px 1px;}
div.myClass1.red {color:red;}
div.myClass2.red {color:red;}
...
div.myClassN.red {color:red;}
Becomes:
div.myClass1 {font-weight:bold;}
div.myClass2 {font-style:italic;}
...
div.myClassN {text-shadow:silver 1px 1px 1px;}
[class~=red] {color:red;}
If you want to apply styles only to an element which is its parents' first child, is it better to use :first-child pseudo-class
.social:first-child{
border-bottom: dotted 1px #6d6d6d;
padding-top: 0;
}
.social{
border: 0;
width: 330px;
height: 75px;
float: right;
text-align: left;
padding: 10px 0;
}
Then, the rule .social has both common styles and the last element's styles.
And .social:first-child overrides them with first element's styles.
You could also use :last-child selector, but :first-childis more supported by old browsers: see
https://developer.mozilla.org/en-US/docs/CSS/:first-child#Browser_compatibility and https://developer.mozilla.org/es/docs/CSS/:last-child#Browser_compatibility.
Another option is to use Descendant selectors
HTML:
<div class="social">
<p class="first">burrito</p>
<p class="last">chimichanga</p>
</div>
Reference first one in CSS: .social .first { color: blue; }
Reference last one in CSS: .social .last { color: green; }
Jsfiddle: https://jsfiddle.net/covbtpaq/153/
Instead of using multiple CSS classes, to address your underlying problem you can use the :focus pseudo-selector:
input[type="text"] {
border: 1px solid grey;
width: 40%;
height: 30px;
border-radius: 0;
}
input[type="text"]:focus {
border: 1px solid #5acdff;
}

How to fit 5 bordered divs exactly inside a containing bordered div

When I try to put 5 inline-block divs of 20% width with 1px borders, inside a containing div, also with a 1px border, they wrap on to the next line.
They do fit if I get rid of all the borders.
I understand that this is because the divs take up 100% of the containing divs area, including its padding and border area, meaning that they don't fit within the borders, so it has to wrap.
My question is how to modify this so that I can make them fit exactly. Surely this is a common problem?
<html>
<head>
<title> Test </title>
<style type=text/css>
div
{
margin: 0;
padding: 0;
}
#navBar
{
border: 1px solid black;
margin-left: auto;
margin-right: auto;
margin-top: 10px;
width: 50%;
}
.navBtn
{
border: 1px solid black;
display: inline-block;
text-align: center;
}
</style>
</head>
<body>
<div id="navBar">
<div class="navBtn" style="width:20%">Text</div><div class="navBtn" style="width:20%">Text</div><div class="navBtn" style="width:20%">Text</div><div class="navBtn" style="width:20%">Text</div><div class="navBtn" style="width:20%">Text</div>
</div>
</body>
</html>
As a side note, it's crazy that if I put the 5 divs on their own lines, they get rendered with space between them, hence why they're all on one line. In my real code the divs are generated with php, so it's not long.
margin:0 -1px 0 -1px gives you an easy place to start.
Would also recommend using float:left for this since display:inline-block is buggy in some browsers.
To get your container <div> to expand vertically to fit content, just have an element with clear:both after your floated ones.
All can be seen here: http://jsfiddle.net/steve/qEJaA/
One idea is to get rid of the 1px border for your .navBtn class, and create a nested element in each navBtn div:
<html>
<head>
<title> Test </title>
<style type=text/css>
div
{
margin: 0;
padding: 0;
}
#navBar
{
border-top: 1px solid black;
margin-left: auto;
margin-right: auto;
margin-top: 10px;
width: 50%;
}
.navBtn
{
display: inline-block;
text-align: center;
}
.nav-text { border:1px solid #ccc; }
</style>
</head>
<body>
<div id="navBar">
<div class="navBtn" style="width:20%"><div class="nav-text">Text</div></div><div class="navBtn" style="width:20%"><div class="nav-text">Text</div></div><div class="navBtn" style="width:20%"><div class="nav-text">Text</div></div><div class="navBtn" style="width:20%"><div class="nav-text">Text</div></div><div class="navBtn" style="width:20%"><div class="nav-text">Text</div></div>
</div>
</body>
</html>
Yes, this is a common problem.
There are (at least) two common solutions.
The first is have a wrapper element for each child element, and move the width to that. The border stays on the child element.
Because your id is navBar, this is obviously for some kind of menu, so I'm going to restructure your code to add the described wrapper elements, and to make it more semantic.
See: http://jsfiddle.net/wFeYn/
<ul id="navBar">
<li style="width:20%">Text</li><li style="width:20%">Text</li><li style="width:20%">Text</li><li style="width:20%">Text</li><li style="width:20%">Text</li>
</ul>
#navBar {
border: 1px solid black;
margin: 10px auto 0 auto;
width: 50%;
margin: 0;
padding: 0
}
#navBar li {
display: inline-block;
text-align: center;
}
#navBar li a {
display: block;
border: 1px solid black;
}
The second solution is to use CSS3's box-sizing: border-box.
This is very easy, and all modern browsers support it (unfortunately IE7 does not).
To use this with your original code you would do:
.navBtn
{
border: 1px solid black;
display: inline-block;
text-align: center;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
If you do care about IE7, then you should know that display: inline-block won't work without some simple hacks.
For IE7 support, replace display: inline-block; with:
display: inline-block;
*display: inline;
zoom: 1;
That goes for either your original code, or my updated code. But only if you care about IE7.

Resources