I have a few div containers with overlays inside of them:
<div class="container">
<div class="overlay"></div>
</div>
<div class="container">
<div class="overlay"></div>
</div>
<div class="container">
<div class="overlay"></div>
</div>
<div class="container">
<div class="overlay"></div>
</div>
The problem is, when I set overlay display to table (it has to be table as I'm centering stuff both vertically & horizontally there - just simplified this example for SO) like so:
.container {
position: relative;
display: inline-block;
background: #fed900;
outline: solid 5px #000;
width: 25%;
height: 200px;
}
.overlay {
position: absolute;
top: 0;
display: table;
background: rgba(0,0,0,0.4);
width: 100%;
height: 100%;
}
I'm getting weird glitch - although developer tools tell me the overlay has the same width as container - in some cases the overlay width equals container's width minus 1 pixel. Why? What am I missing? And how to fix that? :)
http://jsfiddle.net/v13mdq57/
Depending on the width, the calculation is giving you a half pixel (which can't be rendered). We can achieve this without display: table. I'm not quite sure why this only occurs with display: table, but leaving the overlay as a block element fixes the problem.
In this example:
.overlay:before brings inline elements into the middle. It is an invisible element that is lined up on the left hand side inside the overlay.
The closing and opening div tags have no white space between them, which prevents the inline gap.
Read more about removing the gap between inline elements.
CSS / HTML / Demo
body {
margin: 0;
}
.container {
position: relative;
display: inline-block;
vertical-align: middle;
background: #fed900;
width: 25%;
height: 200px;
}
.overlay:before {
content:'';
display: inline-block;
height: 100%;
vertical-align: middle;
}
.overlay {
position: absolute;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.4);
width: 100%;
height: 100%;
text-align: center;
}
<div class="container">
<div class="overlay">Centered</div>
</div><div class="container">
<div class="overlay">Centered</div>
</div><div class="container">
<div class="overlay">Centered</div>
</div><div class="container">
<div class="overlay">Centered</div>
</div>
* {
margin:0px;
padding:0px;
}
.container {
position: relative;
display: inline-block;
background: #fed900;
width: 25%;
height: 200px;
margin-right: -3px;
}
Related
Building an image slideshow, I have a container div of arbitrary size and aspect ratio into which I have to best fit an image, centred, with a caption overlayed at the bottom of the image and fitting its width. My best solution to date is to contain the image and the caption in a child element of the container but I'm having trouble centring it. This should be such a simple thing that I can't believe it's not staring me in the face but I can't see it. The code below uses a portrait format image but I need it to handle landscape also. I'm using React so jQuery is out.
.container {
position: relative;
width: 80%;
height: 48vw;
/* 4:3 */
margin: 0 auto;
display: flex;
justify-content: center;
}
.img-wrap {
background-color: #efe;
}
img {
position: absolute;
max-width: 100%;
max-height: 100%;
}
.caption {
position: absolute;
bottom: 0;
color: #fff;
background-color: rgba(153, 153, 153, 0.541)
}
<div class="container">
<div class="img-wrap">
<img src="https://png.pngtree.com/thumb_back/fw800/background/20190223/ourmid/pngtree-full-aesthetic-aurora-night-sky-background-skystarry-skystarnight-viewbackgroundstar-image_87582.jpg" height="1600px">
<div class="caption">Caption Content</div>
</div>
</div>
Update your code like below:
.container {
width: 80%;
height: 48vw;
/* 4:3 */
margin: 5px auto;
text-align: center;
}
.img-wrap {
background-color: #efe;
height: 100%;
display: inline-block;
position: relative;
}
img {
max-width: 100%;
height: 100%;
display: block;
object-fit: contain; /*or cover if you want to cover all the area*/
object-position: bottom;
}
.caption {
position: absolute;
left: 0;
right: 0;
bottom: 0;
color: #fff;
background-color: rgba(153, 153, 153, 0.541)
}
<div class="container">
<div class="img-wrap">
<img src="https://i.picsum.photos/id/10/400/600.jpg">
<div class="caption">Caption Content</div>
</div>
</div>
<div class="container">
<div class="img-wrap">
<img src="https://i.picsum.photos/id/10/600/300.jpg">
<div class="caption">Caption Content</div>
</div>
</div>
don't position absolute the image,
also if the caption is the sibling of the image,
set the size of the parent and set the image as 100% if the parent's width and height
then you can simply use the text-align: center on the caption to center it.
edit :
keep the existing style of a caption for positioning
fiddle : https://jsfiddle.net/hellooutlook/6ep4Lofz/4/
Is it possible to make a div absolute to a specific relative div rather than just the parent?
For example. I have a div that's contained inside of a row. But, I want it to be absolute in the section rather than the row. Both divs are positioned relative because of a WordPress themes styling. If I use position absolute it will just make it absolute to the row.
How can I get around this issue?
.section {
width: 100%;
height: 100%;
position: relative;
background: #f5f5f5;
}
.row {
width: 80%;
height: 100%;
position: relative;
background: #000000;
margin: 0 auto;
}
.content {
width: 200px;
height: 200px;
background: pink;
position: absolute;
right: 0;
top: 0;
}
<div class="section">
<div class="row">
<div class="content">
</div>
</div>
</div>
This is not how positioning works. A div or any other element is relevant to its parent regarding its positioning. In case you want to position an element inside the section that you have, it's better to construct your code as follows:
<div class="section">
<div class="absoluteDiv">
</div>
<div class="row">
</div>
</div>
You could find some more examples here
Hope it helps,
Konstantinos.
Although you can not make a div absolute to a specific div, one way to get the results you are looking for is to add overflow:visible; to the row and left:100%; to content container. I changed the section height to 300px for demonstration purposes but it will behave the same with 100%.
.section {
width: 100%;
height: 300px;
position: relative;
background: #f5f5f5;
}
.row {
width: 80%;
height: 100%;
position: relative;
background: #000000;
margin: 0 auto;
overflow:visible;
}
.content {
width: 200px;
height: 200px;
background: pink;
position: absolute;
left: 100%;
top: 0;
}
<div class="section">
<div class="row">
<div class="content">
</div>
</div>
</div>
Tried a few things(margin-auto, text align:center etc) to centre this relative div - which is the header in my responsive layout with no luck. Any other ways to try?
The problem is keeping it centered as the page expands/contracts
Its CSS properties are
#header {
height: 170px;
width: 100%;
overflow: visible;
padding: 10px;
margin-bottom: 7px;
position: relative;
z-index: 99;
}
How can a div appear visually centered when it's 100% width of its parent?
Check out this fiddle: https://jsfiddle.net/w6332ytc/
HTML:
<div class="wrapper">
<div class="inner">
Content
</div>
</div>
CSS:
.wrapper {
width: 100%;
background: #000;
height: 300px;
}
.inner {
width: 50%;
background: red;
margin: 0 auto;
}
I have an element in an HTML page with child elements
<div id="parent">
<div class="child01"></div>
<div class="child01"></div>
<div class="child02"></div>
</div>
I have an example with current css at http://jsfiddle.net/exu76qnx/
and I would like to know how to have the child divs align to the bottom of the parent div (without using the absolute position answer I've found online and I would like to keep the float attribute if possible)
I've tried using verticle-align: bottom and positioning elements with a table (which worked) however they would not work for dynamically adding more child elements to the parent div
OPTION 1: You could add a wrapper around these these children which is positioned absolutely.
You can then continue to use floats inside that wrapper.
/*APPEARANCE*/
#parent {
width: 80%;
margin: 0 auto;
height: 100px;
background-color: #BBBBBB;
position: relative;
}
.wrapper {
overflow: hidden;
position: absolute;
bottom: 0;
width: 100%;
background: lightblue;
}
.child01 {
width: 70px;
height: 70px;
background-color: #888888;
}
.child02 {
width: 50px;
height: 30px;
background-color: #888888;
}
/*POSITIONING*/
.child01 {
margin-right: 20px;
float: left;
}
.child02 {
float: right;
}
<div id="parent">
<div class="wrapper">
<div class="child01"></div>
<div class="child01"></div>
<div class="child02"></div>
</div>
</div>
OPTION 2: Alternative with Flexbox (still with wrapper)
/*APPEARANCE*/
#parent {
width: 80%;
margin: 0 auto;
height: 100px;
background-color: #BBBBBB;
position: relative;
display: flex;
flex-direction: column;
justify-content: flex-end
}
.wrapper {
overflow: hidden;
/* quick clearfix */
background: lightblue;
}
.child01 {
width: 70px;
height: 70px;
background-color: #888888;
}
.child02 {
width: 50px;
height: 30px;
background-color: #888888;
}
/*POSITIONING*/
.child01 {
margin-right: 20px;
float: left;
}
.child02 {
float: right;
}
<div id="parent">
<div class="wrapper">
<div class="child01"></div>
<div class="child01"></div>
<div class="child02"></div>
</div>
</div>
I'm still getting to grips with flexbox so it's possible this could be improved.
This might be a case of no school like the old school
I've managed to do it with tables which I wanted to avoid (but not as much as absolute positioning)
http://jsfiddle.net/tefz80jq/
<!-- parent is now a table -->
<table id="parent" cellpadding="0" cellspacing="0" border="0">
<!-- table row handles bottom alignment -->
<tr valign="bottom">
I was hoping for a solution similar to this, being able to dynamically add elements that will fall in line with existing positioning
html:
<div id="main">
<div style="position: absolute; height: 150px; width: 400px; left: 290px;"><img src="HEAD-IMAGE.jpg" /></div>
<div style="position: absolute; height: 300px; width: 233px; top: 180px;"><img src="LEFT-IMAGE.jpg" />(below head)</div>
<div style="position: absolute; top: 200px; left: 270px;">TEXT (next to left image)</div>
</div>
css:
div#main{
position: absolute;
top: 141px; left: 50%;
height: 100%; width: 960px;
padding: 10px;
margin-left: -490px;
text-align: justify;
background-color: yellow;
}
my padding from #main works for my images but not for my text (right & bottom padding).
Why is this happening?
In your example, only the text div has a top and left property. The two divs containing the images only contain one of these properties:
The header div has left: 290px;, so it gets its y-axis position moved by the top padding.
The left div has top: 180px; so it gets its x-axis position moved by the left padding.
The text div has top: 200px; left: 270px; so its x and y-axis are not affected by the padding.
To illustrate this, for this example the text div has had its left property removed. It is now affected by the left padding of its container:
("Show code snippet" and run it)
#main {
position: absolute;
top: 141px;
left: 50%;
height: 100%;
width: 960px;
padding: 50px;
margin-left: -290px;
text-align: justify;
background-color: yellow;
}
.header {
position: absolute;
height: 150px;
width: 400px;
left: 290px;
background: #F00;
}
.left {
position: absolute;
height: 300px;
width: 233px;
top: 180px;
background: #F00;
}
.text {
position: absolute;
top: 200px;
background: #F00;
}
<div id="main">
<div class="header">
<img src="http://www.placehold.it/200" />
</div>
<div class="left">
<img src="http://www.placehold.it/200" />
</div>
<div class="text">You can't handle the truth, soldier!</div>
</div>
Is position: absolute the best way to layout my elements?
Depends... position: absolute removes elements from the normal flow of the document. That is, each element is essentially invisible to the other. This is particularly problematic if you wish to create a flexible layout, which can re-size in accordance with the users browser height / width.
Can you show me another way to layout HTML elements?
Sure! There are many ways to layout a page without resorting to position: absolute. Here is a basic example using display: flex — a newer way to layout elements. It does not enjoy 100% browser support yet, so this is purely an example of one technique :)
Read more:
about vw and vh units on the MDN
about flexbox over on CSS-Tricks - A Complete Guide to Flexbox
about flexbox browser support
Flex example
Note how the elements resize when the example is made full-screen.
* {
margin: 0;
padding: 0;
}
body {
width: 80vw;
max-width: 800px;
margin: 0 auto;
background: #424242;
}
header {
background: #e91e63;
height: 20vh;
}
.wrap {
display: flex;
}
.left {
background: #fce4ec;
flex: 1;
}
.content {
background: #fafafa;
min-height: 70vh;
flex: 2;
}
footer {
height: 10vh;
background: #c51162;
}
<header>
I am header
</header>
<div class="wrap">
<div class="left">
I am sidebar
</div>
<div class="content">
I am content
</div>
</div>
<footer>
I am footer, hear me roar! RWAR!
</footer>
Define a class .child for your <div>
<div class="child">
and define style accordingly
.child { padding: 10px; }
Use position: relative; on the child divs to make them account for the parent divs padding.
problem is you give left and top to text div that why not accept padding,simply remove left to text div then it will accept the padding...