Why does this table-cell overlap the table-cell adjacent to it? - css

JSFiddle here.
This is an SSCCE demonstrating a div with display:table with three child divs having a display:table-cell. The problem is that the .blog-post-slide overlaps the .previous-slide-arrow, rather than being adjacent to it.
The question is why, and how should I solve this problem.
.post-main-area {
display: table;
width: 100%;
}
.post-main-area .previous-slide-arrow,
.post-main-area .next-slide-arrow {
border: 5px solid green;
/*check*/
width: 5%;
display: table-cell;
position: relative;
vertical-align: middle;
left: 20px;
}
.post-main-area .next-slide-arrow {
left: auto;
right: 20px;
}
.post-slide {
border: 5px solid wheat;
/*check*/
width: 90%;
position: relative;
}
<div class="post-main-area">
<a class="previous-slide-arrow" href="#"><</a>
<div class="post-slide">.
<!--<div class="left-part">.</div>
<div class="right-part">.</div>-->
</div>
<a class="next-slide-arrow" href="#">></a>
</div>

Because you shift the first cell 20px to the right:
position: relative;
left: 20px;
Then, as explained in Relative positioning, it overlaps the following cell.
Once a box has been laid out according to the normal flow or floated,
it may be shifted relative to this position. This is called relative
positioning. Offsetting a box (B1) in this way has no effect on the
box (B2) that follows: B2 is given a position as if B1 were not offset
and B2 is not re-positioned after B1's offset is applied. This implies
that relative positioning may cause boxes to overlap.
Instead, I would add some margin to the table:
width: calc(100% - 40px);
margin: 0 20px;
.post-main-area {
display: table;
width: calc(100% - 40px);
margin: 0 20px;
}
.post-main-area .previous-slide-arrow,
.post-main-area .next-slide-arrow {
border: 5px solid green;
width: 5%;
display: table-cell;
vertical-align: middle;
}
.post-slide {
border: 5px solid wheat;
}
<div class="post-main-area">
<a class="previous-slide-arrow" href="#"><</a>
<div class="post-slide">.</div>
<a class="next-slide-arrow" href="#">></a>
</div>

I wouldn't manually move the buttons and stuff, try adding display:table-cell; to .post-slide {} and getting rid of all of the left: and right: attributes like so;
.post-main-area {
display: table;
width: 100%;
}
.post-main-area .previous-slide-arrow,
.post-main-area .next-slide-arrow {
border: 5px solid green;
/*check*/
width: 5%;
display: table-cell;
position: relative;
vertical-align: middle;
}
.post-slide {
border: 5px solid wheat;
display: table-cell;
/*check*/
width: 90%;
position: relative;
}
This allows the computer to position everything like a table, and due to the widths and the order you write the elements in the html document, it should work.

Related

Divider with centered logo in CSS - strange bug when multiple instances are used

I have trouble coding a 1px horizontal seperator line with a logo displayed in the center as pure CSS. Should look like this:
Divider with logo centered
There is a problem with multiple instances: When I add more dividers on a single page only one or two will be displayed with a line, the others will just display the logo.
A question about a centered logo was answered here - but none adressed the bug that happens with multiple instances: Divider with centred image in CSS?
Here is a adapted solution out of that discussion, fiddle below.
CSS:
body {
margin: 0;
background: white;
}
header:after {
content: '';
display: block;
width: 100%;
height: 1px;
background: #ccc;
margin-top: -90px; /* Negative margin up by half height of logo + half total top and bottom padding around logo */
}
.logo {
position: relative; /* Brings the div above the header:after element */
width: 200px;
height: 100px;
padding: 40px;
margin: 0 auto;
background: white url("http://placehold.it/200x100") no-repeat center center;
}
.logo img {
display: block;
}
HTML:
<body>
<header>
<div class="logo">
</div>
<div class="logo">
</div>
<div class="logo">
</div>
</header>
</body>
The fiddle:
http://jsbin.com/delixecobi/edit?html,css,output
I totally changed the CSS. Give the .logo a position: relative and :after a position: absolute. You are using it for one single header. That's why it didn't work.
body {
margin: 0;
background: white;
}
.logo:after {
content: ' ';
display: block;
width: 100%;
height: 1px;
background: #ccc;
position: absolute;
top: 50%;
margin-top: -1px;
left: -50%;
width: 200%;
}
.logo {
position: relative; /* Brings the div above the header:after element */
width: 200px;
height: 100px;
padding: 40px;
margin: 0 auto;
background: white url("http://placehold.it/200x100") no-repeat center center;
}
.logo img {
display: block;
}
<header>
<div class="logo">
</div>
<div class="logo">
</div>
<div class="logo">
</div>
</header>
Preview
If you want the line not to cross or cut, use a negative z-index.
I found a solution also for my question how to get text centered within the div - thanks to web-tiki for his approach here: Line before and after title over image
In the JSBin I put all together and formatted / commented it a bit to make it easy to work with. You will find:
divider formats with img, text and text in multiple lines
stable in multiple instances
body {
margin: 0;
background: white;
}
.logo:after {
content: ' ';
display: block;
width: 100%;
height: 1px;
background: #ccc;
position: absolute;
top: 50%;
margin-top: -1px;
left: -50%;
width: 200%;
z-index: -1;
}
.logo {
position: relative;
/* Brings the div above the header:after element */
width: 200px;
height: 100px;
padding: 20px;
/* also padding between line and logo */
margin: 0 auto;
background: white url("http://placehold.it/200x100") no-repeat center center;
}
.logo img {
display: block;
}
.logotext {
width: 100%;
margin: 20 auto;
overflow: hidden;
text-align: center;
font-weight: 300;
color: green;
/* color text */
}
.logotext:before,
.logotext:after {
content: "";
display: inline-block;
width: 50%;
margin: 0 20 0 -55%;
/* 2nd no: space text to line on the left */
vertical-align: middle;
border-bottom: 1px solid #ccc;
/* last: color line */
}
.logotext:after {
margin: 0 -55% 0 20;
/* last no: space text to line on the right */
}
span {
display: inline-block;
vertical-align: middle;
}
<header>
<div class="logo">
</div>
<div class="logo">
</div>
<div class="logotext">
somesome</div>
<div class="logotext">
somesome</div>
</header>
One major drawback to this solution is that it does not allow the width of the line to be defined to % of the main viewport.

Expanding height of parent div based on children's height

I know there are several similar questions answered here, but I can not seem to get this working.
I have two parent divs - one is like a frame with a border and padding, the second is a solid black background, and the third is where a transparent image will actually be placed. I need the two parent divs to expand their height based on the image's height.
I have this working for the div with the black background, but I can't get the parent div with the border to expand it's size:
Here is the fiddle: http://jsfiddle.net/vpdj4kst/
#builder_container {
width: 100%;
/*overflow: auto;*/
position: relative;
padding: 8px;
border: 1px solid #ccc;
margin-bottom: 15px;
display: inline-block;
clear: both;
}
#builder_contents {
background: #000;
width: 100%;
height: 100%;
position: relative;
display: block;
}
.builder_img {
width: 100%;
height: auto;
position: absolute;
}
<div id="builder_container">
<div id="builder_contents">
<img class="builder_img" src="image.png" />
</div>
</div>
This is because you have set the image to position: absolute; which will take it out of the flow causing the parent elements to act as if it wasn't there.
Elements that are positioned relatively are still considered to be in
the normal flow of elements in the document. In contrast, an element
that is positioned absolutely is taken out of the flow and thus takes
up no space when placing other elements.
Position (https://developer.mozilla.org/en-US/docs/Web/CSS/position)
Remove position: absolute; from .builder_img and the parent containers will react to its height.
#builder_container {
width: 100%;
/*overflow: auto;*/
position: relative;
padding: 8px;
border: 1px solid #ccc;
margin-bottom: 15px;
display: inline-block;
clear: both;
}
#builder_contents {
background: #000;
width: 100%;
height: 100%;
position: relative;
display: block;
}
.builder_img {
width: 100%;
height: auto;
}
<div id="builder_container">
<div id="builder_contents">
<img class="builder_img" src="http://coolspotters.com/files/photos/1036167/adidas-st-girls-straw-hat-profile.png" />
</div>
</div>

DIVs and CSS layout not lining up, but why?

I'm trying to layout a screen using div's and CSS. It's a simple layout at this point but I can't seem to get the div's to line up. I want one wrapper div with two div's within it: one aligned to the left and one aligned to the right. However, they end up on top of each other.
I know this question is simple. What am I missing here?
If I reduce the width of the right div to 60% it lines up right but shouldn't I be able to use 100% of the width of the parent div?
#product_wrapper {
display: inline-block;
height: 75%;
width: 75%;
background-color: white;
text-align: top;
margin: 0 auto;
}
#images_wrapper {
background-color: red;
display: inline-block;
height: 100%;
width: 30%;
margin: 0;
padding: 0;
}
#content_wrapper {
background-color: blue;
display: inline-block;
height: 100%;
width: 70%;
margin: 0;
padding: 0;
}
<div id="product_wrapper">
<div id="images_wrapper">Foo</div>
<div id="content_wrapper">Bar</div>
</div>
Float left your children elements:
jsBin demo
#product_wrapper > *{float:left;}
Note that inline-block causes the inner elements to actually act like inline elements
where white spaces count!
SO another way would be to modify your HTML removing the NewLine separator:
jsBin demo
<div id="images_wrapper">
Foo content
</div><div id="content_wrapper">
^^-------------------------------------- no space here
Bar content
</div>
The third way (the worst one) is to set font-size to 0 for the parent (will remove logically the child's white-space gap since is now '0'); >> and than reset the font-size for children elements to px (cause em will not work since parent has 0).
But that's a good way to loose track of dynamic and responsive font sizes expecially if you use em and size inheritances.
The problem is the whitespace in the html, which occupies some space between the elements.
One way of fixing it is
#product_wrapper {
font-size: 0; /* Hide whitespace in the html */
}
#images_wrapper, #content_wrapper {
font-size: 16px; /* Reset to whatever vaue */
}
#product_wrapper {
display: inline-block;
height: 75%;
width: 75%;
background-color: white;
text-align: top;
margin: 0 auto;
font-size: 0;
}
#images_wrapper, #content_wrapper {
font-size: 16px;
}
#images_wrapper {
background-color: red;
display: inline-block;
height: 100%;
width: 30%;
margin: 0;
padding: 0;
}
#content_wrapper {
background-color: blue;
display: inline-block;
height: 100%;
width: 70%;
margin: 0;
padding: 0;
}
<div id="product_wrapper">
<div id="images_wrapper">Foo</div>
<div id="content_wrapper">Bar</div>
</div>
Use float:left instead of display:inline-block
#product_wrapper {
display: inline-block;
height: 75%;
width: 75%;
background-color: white;
text-align: top;
margin: 0 auto;
}
#images_wrapper {
background-color: red;
float:left;
height: 100%;
width: 30%;
margin: 0;
padding: 0;
}
#content_wrapper {
background-color: blue;
float:left;
height: 100%;
width: 70%;
margin: 0;
padding: 0;
}
<div id="product_wrapper">
<div id="images_wrapper">Foo</div>
<div id="content_wrapper">Bar</div>
</div>

absolute positioning on :before element on element with display: table-cell

I have a row of elements and I want to style them using display: table-cell; to make the text position vertically in the middle. Sometimes a row will have an active state where I need to add a horizontal bar on top of the active element. This bar needs to be at least one pixel removed from the row. I used the :before pseudo element for this and it works great in Chrome, but not in Firefox because of the display: table-cell;.
Is there any solution for this? Preferably one without javascript.
Works in Chrome, not in Firefox: http://jsfiddle.net/Danny_Joris/CYwUZ/
<div id="wrapper">
<div class="col1">col1 col1 col1</div>
<div class="col2">col2 col2 col2</div>
<div class="col3">col3 col3 col3</div>
</div>
#wrapper {
margin: 40px 0 0 0;
position: relative;
background: yellow;
display: inline-block;
}
#wrapper > div {
width: 33%;
display: table-cell;
vertical-align: middle;
height: 75px;
width: 60px;
border: 1px solid #ccc;
text-align: center;
position: relative;
}
.col2:before {
content: '';
position: absolute;
top: -7px;
height: 5px;
background: lightblue;
left: -1px;
right: -1px;
z-index: 50;
}

Problems implementing a carousel

I'm trying to implement a responsive carousel by myself for a webpage I'm designing. I'm having some issues that may be thousends times easier to ilustrate with some screenshots, so here it goes:
So as you see, I have two arrows to slice the items and a horizontall scrollbar.
The arrows are floated to the left and right respectively, and the items are just inline-block divs inside a div.items container, which has a width of 90% (and overflow-x: scroll or course).
SO now, if I append another item to the DOM, I end with this:
Why did the fourth item go below? I'm not floating the items, and as I specified and horizontal scroll, I would expect it to be at the back and to be able to see it with the scrollbar.
What am I missing?
I'll paste relevant code:
HTML:
<div class="grid">
<div class="left-arrow"></div>
<div class="items">
<div class="item">...</div>
<div class="item">...</div>
<div class="item">...</div>
<div class="item">...</div>
</div>
<div class="right-arrow"></div>
</div>
CSS:
div.grid {
margin-top: 20px;
padding: 10px 75px;
text-align: center;
z-index: 1000;
}
div.grid .left-arrow, div.grid .right-arrow {
position: relative;
top: 70px;
}
div.grid .left-arrow {
float: left;
width: 0;
height: 0;
margin: 0 30px 0 -50px;
border-top: 50px solid transparent;
border-bottom: 50px solid transparent;
border-right: 35px solid #ddd;
}
div.grid .right-arrow {
float: right;
width: 0;
height: 0;
margin: 0 -50px 0 30px;
border-top: 50px solid transparent;
border-bottom: 50px solid transparent;
border-left: 35px solid #ddd;
}
div.items {
display: inline-block;
z-index: 100;
width: 90%;
overflow-x: scroll;
}
div.item {
margin: 10px;
display: inline-block;
position: relative;
left: 0;
}
EDIT: Oreilly has exactly what I'm looking forward to achieve:
http://shop.oreilly.com/category/browse-subjects/programming.do
The container is growing in height to accommodate the additional items. I believe that you should be able to get the effect you are looking for by setting a specific height on the container element.
Edit: After testing some more, it turns out setting the height won't actually have any impact on this. You need to set white-space: nowrap; to get it to actually work.
Here's the full CSS for the div.items (which is all I changed to get this to work in my tests):
div.items {
display: inline-block;
z-index: 100;
width: 90%;
overflow-x: scroll;
white-space: nowrap;
}

Resources