I have 2 ids on my page as;
<div id="a">
<div id="b"></div>
</div>
With styling;
#a {
height: 25px;
width: 100px;
background-color: #9DBA6A;
}
#b {
height: 25px;
width: 25px;
background-color: #FF7E00;
}
I want to stick div b on div a's bottom with some -ve margin or padding and I want to remain its position like that when div a's height changes. The layout cannot be altered.
Here is a diagram;
You can see my fiddle here and the complete layout here.
Check out this fiddle... http://jsfiddle.net/23gCd/
I've kept your <div id="b"></div> inside your <div id="a"></div>. It will stay below #a no matter the height, but if #b's height changes, you'd have to change it in the CSS.
CSS
#a {
height: 25px;
width: 100px;
background-color: #9DBA6A;
position: relative;
}
#b {
height: 25px;
width: 25px;
background-color: #FF7E00;
position: absolute;
bottom: -25px;
}
Adding the position: relative property to #a allows us to absolutely position #b relative to where #a is. So you can offset #b -25px from the bottom; if the height of #b changes, you'd have to change that offset as well.
I have tried this in your fiddle and it worked:
#a {
height: 10px;
width: 100px;
background-color: #9DBA6A;
position : relative;
}
#b {
height: 25px;
width: 25px;
background-color: #FF7E00;
position : absolute;
bottom : -25px;
}
greetings
Mh, I don't know a solution for doing this with plain css if the height is not hardcoded. But if the height is hardcoded, just use margin-top: 25px; on b...
How would you want to change the height of a? Or would you remove the height: 25px; in your production code?
Another way is setting position:relative on parent (that's not bad!) and position:absolute on child. The positions of child will be computed according to parent so bottom:0 will stick it to bottom.
See http://jsfiddle.net/shP3D/12/
Related
I want to set a width of ::before pseudo-element to 80%. If I use positioning then everything works, but if I don't use it then everything fails.
Could you explain me why percentage width doesn't work without positioning? If you can please add some references to the specification
.positioned {
position: relative;
height: 15px;
background-color: aquamarine;
margin-bottom: 10px;
}
.positioned::before {
position: absolute;
content: "";
background: red;
width: 80%;
height: 100%;
}
.not-positioned {
height: 15px;
background-color: aquamarine;
margin-bottom: 10px;
}
.not-positioned::before {
content: "";
background: red;
width: 80%;
height: 100%;
}
<div class="positioned"></div>
<div class="not-positioned"></div>
First, it's not about percentage values. You will have the same result even with pixel values and both width and height aren't working.
Pseudo elements are inline elements and their width/height is only defined by their content and the width/height set with CSS will be ignored.
In CSS, ::before creates a pseudo-element that is the first child of the selected element. It is often used to add cosmetic content to an element with the content property. It is inline by default. ref
width
This property does not apply to non-replaced inline elements. The content width of a non-replaced inline element's boxes is that of the rendered content within them ref
The 'height' property does not apply. The height of the content area should be based on the font ... ref
By making the pseudo element position:absolute you will now consider the rules that applies to Absolutely positioned element in order to calculate width and height. You will also notice that the element will have a computed value of block within display.
You should also pay attention to the use of positioned element which means either relative, absolute, fixed or sticky BUT making the element position:relative will keep it an inline level element and you still cannot use width/height.
.positioned {
position: relative;
height: 15px;
background-color: aquamarine;
margin-bottom: 10px;
}
.positioned::before {
position: relative;
content: "";
background: red;
width: 80%;
height: 100%;
}
.not-positioned {
height: 15px;
background-color: aquamarine;
margin-bottom: 10px;
}
.not-positioned::before {
content: "";
background: red;
width: 80%;
height: 100%;
}
<div class="positioned"></div>
<div class="not-positioned"></div>
This said, you can simplify you code by considering gradient if you want to achieve the same visual:
.positioned {
position: relative;
height: 15px;
background:
linear-gradient(red,red) left/80% 100% no-repeat,
aquamarine;
margin-bottom: 10px;
}
<div class="positioned"></div>
Assume the parent is relative, the child (style-x) is absolute. I used top 50%, left 25% to center the child.
I wish to actually center the child, so I set transform: translate(-50%, -50%). I am unsure if this is centered, so I double check by deleting that line and adding 'margin-top: -55px;' (half of the height), and 'margin-left: -45px;' (half of the width).
These two lines position my element in slightly different locations, yet this is different from my model of CSS. What's going on?
body {
height: 100%;
width: 100%;
margin: 0 auto;
}
#main {
overflow: auto;
height: 64vh;
width: 38vw;
margin: 0 auto;
margin-top: 10%;
position: relative;
border: 1vh solid black;
overflow: hidden;
}
#style-x {
/*Why doesn't translate(-50%, -50%) give me
the same position as setting the margin top and
left to half of the width and height?*/
width: 90px;
height: 110px;
/*
transform: translate(-50%, -50%);*/
margin-top: -55px;
margin-left: -45px;
position: absolute;
top: 50%;
left: 25%;
padding: 2%;
text-align: center;
background: green;
}
#left-col {
float: left;
width: 4%;
height: 101%;
margin-left: 46%;
background: black;
}
#right-col {
float: left;
width: 4%;
height: 101%;
margin: 0 auto;
margin-left: 0;
background: black;
}
<body>
<section id='main'>
<div id='style-x'>X</div>
<div id='left-col'></div>
<div id='right-col'></div>
</section>
</body>
Here's my Codepen if you'd like a visualization.
http://codepen.io/sentedelviento/pen/ORyqzv
There is no problem in your method. Both will try to center based on the values you provide.
The margin method fails cos you aren't using a Box Sizing method like so.
box-sizing: border-box
This results in all your elements to be larger than the height and width specified. Without this, you are telling the browser to add any padding or border to both width & height.
And so your larger element shifts when using using the margin method.
You've set a 2% padding on style-x, and a width of 38vw on #main. When using margins to center things, you would need to account for these varying values.
When you set a percentage padding, its calculated based on the width of the containing block.
The transform method on the other hand, uses the bounding box of the containing block and has no problem centering a larger element.
I'd suggest you include this box-sizing on main and style-x if using the margin method. You could just use
*, after, before {
box-sizing: border-box;
}
This gives better control over dimensions across all elements.
Is there something about CSS that doesn't allow you to specify both top and bottom or left and right values?
Take this example:
div {
width: 100px;
height: 100px;
}
.first {
background-color: blue;
position: relative;
left: 100px;
right: 50px;
}
.second {
background-color: yellow;
}
<div class="first"></div>
<div class="second"></div>
Try removing right: 50px and the position will remain the same. What's going on?
In your example, the element has a fixed width to 100px and you are specifying both left and right properties. On MDN, you can read (emphasis mine) :
When both the right CSS property and the left CSS property are
defined, the position of the element is overspecified. In that case,
the left value has precedence when the container is left-to-right
(that is that the right computed value is set to -left)[...]
So in your example the right value is ignored. For the bottom property, the same rule applies as the element's height is fixed.
Note that this rule only applies for non static positioning
You can combine left/right and top/bottom, but if width/height is also present, their value take precedence, which makes some sense, as how can it be both at a certain right/bottom position and have a certain width/height.
This sample shows how it behaves.
body {
margin: 0;
}
.first, .second {
width: 50px;
height: 50px;
}
.first {
background-color: yellow;
}
.second {
background-color: blue;
position: absolute;
left: 50px;
right: 50px;
top: 50px;
bottom: 50px;
}
.third {
background-color: green;
position: absolute;
left: 100px;
right: 100px;
top: 100px;
bottom: 50px;
}
<div class="first"></div>
<div class="second"></div>
<div class="third"></div>
From MDN:
When both the right CSS property and the left CSS property are
defined, the position of the element is overspecified. In that case,
the left value has precedence when the container is left-to-right
(that is that the right computed value is set to -left), and the right
value has precedence when the container is right-to-left (that is that
the left computed value is set to -right).
Here's part of a design:
As you can see - its simply a button that is exactly positioned between the two divs. The code is simply:
<div class="uc-apply-widget1">
<div class="top">
</div>
<div class="bottom">
<a>Get Started</a>
</div>
</div>
.uc-apply-widget1
{
.top
{
background-color:#primary-color;
height:30rem;
}
.bottom
{
background-color:#primary-600;
padding:0 1.6rem 1.6rem 1.6rem;
a
{
margin-top:-2.8rem;
}
}
}
However, I've come across a problem with using negative margins. I expected to just be able to move the button outside of the bottom div by applying a half height negative margin. Although the button does move upwards, it doesn't move the full 2.8 rem - the amount of movement is the same even if I apply 50rem.
The other solution is to use position relative, which does move the button up, but does not drag the bottom div upwards with it.
So I'm looking to move the button up by n amount and reduce the bottom div height by n amount - any ideas - I may just be having a bad day.
use
position: absolute;
top: 0; left: 0;
transform: translateY(-50%);
on your button
https://developer.mozilla.org/en-US/docs/Web/CSS/transform
Here is one way of realizing your design.
Set the a element to have display: table and position: absolute with
top and left offsets to 0 and 50% respectively.
The display: table rule will give you a shrink-to-fit width, which may be what you need.
You can then use the CSS3 transform property to translate the element by -50% both in the X and the Y directions to get the centering.
The advantage here is that you don't have to specify the dimensions for the a element.
.uc-apply-widget1 {
width: 400px;
margin: 0 auto;
}
.top {
background-color: beige;
height: 10rem;
}
.bottom {
background-color: lightgray;
height: 5rem;
padding: 0 1.6rem 1.6rem 1.6rem;
position: relative;
}
a {
display: table;
width: auto;
margin: 0 auto;
padding: 10px;
border: 1px dotted blue;
position: absolute;
top: 0;
left: 50%;
transform: translateY(-50%) translateX(-50%);
}
<div class="uc-apply-widget1">
<div class="top">
</div>
<div class="bottom">
<a>Get Started</a>
</div>
</div>
I have a div of width: 1000px and inside that is a child which I wish to span the entire width of the browser window.
The trouble is, I don't know how to override previous width inheritance.
I could just position this outside of my container div, but that would be a huge inconvenience and workaround, unless of course this is equally as troublesome.
Markup:
<div class="centreContainer">
<div class="menuContainer"></div>
</div>
CSS:
html, body
{
margin: 0;
padding: 0;
}
.centreContainer
{
margin: auto;
width: 1000px;
}
.menuContainer
{
width: <what to do>;
height: 420px;
}
Preferably I would like a CSS only workaround, I was thinking of some stupid Javascript solution where you get the width of the browser window, then set the width of the menuContainer to:
<variable> / 10 (10 because 1000 / 100 = 10, where 1000 is the width of the centre container)
And have the menuContainer set on margin: auto; so it is centered.
Just use position:
.menuContainer
{
position: absolute;
width: 100%;
height: 420px;
}
Just use position:absolute shown in this jsfiddle
.menuContainer
{
width: 100%;
height: 420px;
position: absolute;
}
you could try placing your .menuContainer as absolute position into a relative parent position . JSfiddle
#root{
display:block;
position: relative;
}
.menuContainer{
position:absolute;
top: 50px;
left: 0;
}