I want to center 4 small, square child divs along each edge of a square parent div. My current solution depends on hacked-together absolute positioning. http://jsfiddle.net/Lrc4h/
HTML:
<div class="tile">
<div class="tile_inner"></div>
<div class="exit_left"></div>
<div class="exit_right"></div>
<div class="exit_up"></div>
<div class="exit_down"></div>
</div>
CSS:
.tile {
float: left;
width: 180px;
height: 180px;
background-color: gray;
border: 2px solid black;
}
.tile_inner {
width: 120px;
height: 120px;
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border: 1px solid white;
}
.exit_left {
position: absolute;
top: 90px;
width: 20px;
height: 20px;
border: 3px solid pink;
}
.exit_right {
position: absolute;
left: 165px;
top: 90px;
width: 20px;
height: 20px;
border: 3px solid red;
}
.exit_up {
position: absolute;
left:90px;
top:10px;
width: 20px;
height: 20px;
border: 3px solid blue;
}
.exit_down {
position: absolute;
left:90px;
top:165px;
width: 20px;
height: 20px;
border: 3px solid green;
}
How can I get each of the exit directions centred along the edge of each axis?
Here is an updated snippet: http://jsfiddle.net/Lrc4h/3/
First of all you need to know that when you're using position: absolute the element will position with absolute coordinates based on the first parent that is position: absolute or position: relative falling back to the document if there is none.
Secondly it's important, when dealing with borders like in your example, to understand the box model and how nasty things get when borders cross the borders ;-). It's a common practice to use box-sizing: border-box to make things a bit easier and to mix relative and absolute units nicely. I've included a box model initialization how I prefer it on the top of the example I've posted.
Combining all this together you can start use relative units (percentage) in your absolute positioning. The example I've posted is still using absolute positions but relative to the .tile element. You should always make your absolute positions relative to a parent. Using left: 50% centers the start of your element to the center of your parents width. However, as your exit element also has a width this needs to be compensated by half of it's width. That's why there is a margin-left: -15px. You could also use the calc function if browser support is IE9+. This would look like this: left: calc(50% - 15px).
As you can see the example still has absolute positions and this problem is easy to solve with absolute positioning. You still have to "hard code" a few values, but they are all relative to the parent and you can easily change your .tile dimensions without changing the child elements.
Cheers
Gion
.tile_inner {
width: 120px;
height: 120px;
position: relative;
top: 50%;
left: 50%;
margin: -60px 0 0 -60px;
border: 1px solid white;
}
You just need to adjust the margin
Demo
.tile_inner{
margin: -60px 0 0 -60px;
}
Maybe as not as clean as it can get, but you can use the calc function to use percentages in conjunction with pixels (based on the width & height of the child divs. For example (I'm including only the changes to the CSS code:
.tile {
position: relative;
}
.exit_left {
top: calc(50% - 13px);
}
.exit_right {
left: calc(100% - 26px);
top: calc(50% - 13px);
}
.exit_up {
left: calc(50% - 13px);
}
.exit_down {
left: calc(50% - 13px);
top: calc(100% - 26px);
}
In that way, even when you change the parent div's dimensions, the child divs will remail in place.
Demo: http://jsfiddle.net/xPP32/
Here's slightly optimized version that relies on pseudo-elements and relative units of measurement (%). Scaling this one is a breeze. All you need to do is change the height and width on the .tile and the rest is taken care of. Here's the original square: http://jsfiddle.net/MGse6/. And, here's a square scaled up: http://jsfiddle.net/k9dxW/.
HTML:
<div class="tile">
<div></div>
</div>
CSS:
*, :before, :after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
padding: 10px;
}
.tile {
width: 180px;
height: 180px;
background-color: gray;
border: 2px solid black;
position: relative;
}
.tile > div {
width: 65%;
height: 65%;
border: 1px solid #fff;
margin: 17.5% auto 0;
}
.tile:before,
.tile:after,
.tile > div:before,
.tile > div:after {
content: "";
position: absolute;
width: 16%;
height: 16%;
border: 3px solid;
}
.tile:before {
top: 0;
left: 50%;
margin-left: -8%;
border-color: blue;
}
.tile:after {
top: 50%;
right: 0;
margin-top: -8%;
border-color: red;
}
.tile > div:before {
bottom: 0;
left: 50%;
margin-left: -8%;
border-color: green;
}
.tile > div:after {
top: 50%;
left: 0;
margin-top: -8%;
border-color: pink;
}
And, here's another solution where elements are arranged using flow: http://jsfiddle.net/xep9M/.
HTML:
<div class="tile">
<!--
It's very important
to have the divs stack
next to each other
-->
<div></div><div></div><div></div><div></div><div></div>
</div>
CSS:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
padding: 10px;
}
.tile {
width: 180px;
height: 180px;
background-color: gray;
border: 2px solid black;
box-sizing: content-box;
}
.tile > div {
width: 16%;
height: 16%;
display: inline-block;
border: 3px solid;
}
.tile > div:first-of-type,
.tile > div:last-of-type {
display: block;
margin: 0 auto;
}
.tile > div:first-of-type {
margin-bottom: 1.5%;
border-color: blue;
}
.tile > div:last-of-type {
margin-top: 1.5%;
border-color: green;
}
.tile > div:nth-of-type(3) {
height: 65%;
width: 65%;
border: 1px solid #fff;
}
.tile > div:nth-of-type(n + 2) {
vertical-align: middle;
}
.tile > div:nth-of-type(2) {
margin-right: 1.5%;
border-color: pink;
}
.tile > div:nth-of-type(4) {
margin-left: 1.5%;
border-color: red;
}
Related
I would like to have a 5px margin around each of my divs but when I add it in CSS, there is a 5px margin on every side except for in between the divs and on the bottom. The two divs also overflow off the page on the bottom. I understand this is because of the 5px margin on top pushing the divs off screen. I am unsure how to make it just add the margin all around and shrink the divs accordingly.
* {
box-sizing: border-box;
margin: 0;
}
html {
width: 100%;
height: 100%;
}
body {
background: black;
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
}
.one {
background: red;
position: absolute;
width: 10%;
height: 100%;
left: 0;
border: 3px solid green;
border-radius: 5px;
margin: 5px;
}
.two {
background: blue;
position: absolute;
width: 90%;
height: 100%;
right: 0;
border: 3px solid green;
border-radius: 5px;
margin: 5px;
}
<div class="one">
</div>
<div class="two">
</div>
Resulting Page
Divs pushed off screen on bottom and no margin in-between divs. 5px margin on top, left, and right is present.
I am new to HTML and CSS so any helps greatly appreciated.
Use CSS Flex
/*QuickReset*/ * { box-sizing: border-box; margin: 0; }
html {
height: 100%;
}
body {
background: black;
height: 100%;
position: relative;
display: flex; /* Use flex! */
padding: 5px; /* Instead of children margin */
/* gap: 5px; /* Uncomment to add a gap between your child elements! */
}
.one,
.two {
border: 3px solid green;
border-radius: 5px;
}
.one { width: 10%; background: red; }
.two { width: 90%; background: blue; }
<div class="one">
</div>
<div class="two">
</div>
box-sizing: border-box does not include handling/including of margins in the overall width or height of the elements, only padding and borders. Therefore you have to subtract the margin values from the width or height values.
In your case you should use calc values on all height and width settings where there's a margin. I.e. if you have 5px margin (= on all sides), use for example calc(100% - 10px) where you want 100% width or height. Similar with other percentage values - see your adapted code below:
* {
box-sizing: border-box;
margin: 0;
}
html {
width: 100%;
height: 100%;
}
body {
background: black;
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
}
.one {
background: red;
position: absolute;
width: calc(10% - 10px);
height: calc(100% - 10px);
left: 0;
border: 3px solid green;
border-radius: 5px;
margin: 5px;
}
.two {
background: blue;
position: absolute;
width: calc(90% - 10px);
height: calc(10% - 10px);
right: 0;
border: 3px solid green;
border-radius: 5px;
margin: 5px;
}
<div class="one">
</div>
<div class="two">
</div>
using the css calc function on the width of .two to subtract 10px (2x5px margins) from the 90% width, appears to give a reasonable margin.
width: calc(90% - 10px);
I am not sure why there is not a visible 10px (2x5px) margin between .one and .two though.
https://developer.mozilla.org/en-US/docs/Web/CSS/calc
* {
box-sizing: border-box;
margin: 0;
}
html {
width: 100%;
height: 100%;
}
body {
background: black;
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
}
.one {
background: red;
position: absolute;
width: 10%;
height: 100%;
left: 0;
border: 3px solid green;
border-radius: 5px;
margin: 5px;
}
.two {
background: blue;
position: absolute;
width: calc(90% - 10px);
height: 100%;
right: 0;
border: 3px solid green;
border-radius: 5px;
margin: 5px;
}
<div class="one">
</div>
<div class="two">
</div>
Hi I have a question about my code.
Here is my problem.
I have two items and one frame. Frame has position relative a two items (children) have position absolute. They should be always on the same point inside my frame but when I am resizing the position of children are different in relation with frame. How to make the children always stay on same position for responzive design? Is it possible?
Try to change height of window in example too (not only width)
https://codesandbox.io/s/adoring-jackson-c6fth?file=/index.html:0-900
.frame {
width: 70vh;
height: 90vh;
border: 10px solid red;
margin: 10px auto;
position: relative;
}
.objA {
width: 130%;
position: absolute;
height: 40%;
bottom: -10%;
left: -20;
border: 2px solid green;
background: rgba(10, 101, 10, 0.7);
z-index: 2;
}
.objB {
width: 10%;
position: absolute;
height: 20%;
bottom: 20%;
left: 30%;
background: red;
z-index: 1;
}
<div class="frame"></div>
<div class="objA"></div>
<div class="objB"></div>
I post here my real example image for better imagination what the problem is.
All objects are positioned absolute (Waves, stars, robot etc...) Each wave should in every resized situation be in same position. Good to know is that every wave is separatly.
Make sure the positions and heights/widths are all in percents and most important: place your items inside the main <div class="frame"></div> element. You can start this way:
* {
box-sizing: border-box;
}
body {
background: none #014653;
margin: 0;
}
.frame {
width: 70vw;
height: 90vh;
border: 10px solid #5cb9b8;
background: none #5cb9b8;
margin: 5vh auto;
position: relative;
border-radius: 6px;
}
.frame-stage {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border: 5px solid #a2cece;
background: none #014653;
border-radius: 5px;
}
.objA {
width: 10%;
position: absolute;
height: 20%;
bottom: 10%;
left: -20;
border: 2px solid green;
background: rgba(10, 101, 10, 0.7);
z-index: 2;
}
.objB {
width: 10%;
position: absolute;
height: 20%;
bottom: 30%;
left: 30%;
background: red;
z-index: 1;
}
<div class="frame">
<div class="frame-stage">
<div class="objA"></div>
<div class="objB"></div>
</div>
</div>
Updated codesandbox here.
div {
margin: 50px;
position: relative;
background-color: red;
width: 200px;
height: 50px;
border: 2px solid black;
}
div::after {
content: '';
position: absolute;
background-color: green;
width: 100px;
height: 100px;
border-radius: 100%;
top: -25px;
left:50px;
border: 2px solid black;
}
div.overflow-hidden {
overflow: hidden;
}
<div>1st</div>
<div class="overflow-hidden">2nd</div>
1st case: as expected.
2nd case[overflow-hidden]: Middle part of top and bottom border should be green. Looks like circle is not above its parent div's border. Is there any way to make it above it? Whats happening here? Will the z-index work?
Why is this happening?
This is because overflow: hidden; clips the content to the content box.
hidden
Content is clipped if necessary to fit the content box. No scrollbars
are provided.
MDN Web docs - https://developer.mozilla.org/en/docs/Web/CSS/overflow
This can be seen in the first example below as I have changed the border to be transparent.
What can you do?
One way to get around this would be to apply the border using an absolutely positioned pseudo element instead of to the containing div.
div {
background-color: red;
height: 50px;
margin: 50px;
overflow: hidden;
position: relative;
width: 200px;
}
div::after {
background-color: green;
border: 2px solid black;
border-radius: 100%;
content: '';
height: 100px;
left: 50px;
position: absolute;
top: -25px;
width: 100px;
}
div.overflow-with-border {
border: 2px solid transparent;
}
div.overflow-with-pseudo {
padding: 2px;
}
div.overflow-with-pseudo::before {
border: 2px solid black;
box-sizing: border-box;
content: '';
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
<div class="overflow-with-border">1st</div>
<div class="overflow-with-pseudo">2nd</div>
Here is the fiddle.
I have two div elements.
<div class="parent">
<div class="child">
</div>
</div>
And CSS code for that.
.parent {
height: 20px;
width: 100px;
background-color: #080;
position: relative;
}
.child {
position: absolute;
width: 80px;
height: 200px;
background-color: #008;
right: -10px;
top: 30px;
}
.child:before {
border-right: 10px solid transparent;
border-bottom: 10px solid #008;
border-left: 10px solid transparent;
top: -10px;
width: 0;
height: 0;
content: "";
position: absolute;
left: 50%;
}
How to position .child:before related to .parent without JS. I know solution with .parent:before, but it is not good for me.
I think this is what you are trying to do.
I think you will find this more robust and scalable.
.parent {
height: 20px;
width: 100px;
background-color: #080;
position: relative;
}
.child {
position: absolute;
width: 80px;
height: 200px;
background-color: #008;
left: 50%;
/* note 50% */
top: 30px;
margin-left: -20px;
/* 2x your arrow size */
}
.child:before {
position: absolute;
border-right: 10px solid transparent;
border-bottom: 10px solid #008;
border-left: 10px solid transparent;
top: -10px;
/* your border size */
margin-left: 10px;
/* your border-size */
width: 0;
height: 0;
content: "";
left: 0;
}
<div class="parent">
<div class="child">
</div>
</div>
You can only position an element absolutely in relation to the closest parent that is itself positioned. In your case, that's .child.
If .child and .child:before are not related in your layout, why not put .child:before in the parent element, either as .parent:before, or as its own element?
Alternatively, if your elements both have fixed widths as in your example, just give the pseudo-element a fixed pixel position as well. Demonstration.
this is my html
a.html
<div class='main'>
<div class="sub1"></div>
<div class="sub2"></div>
</div>
and css:
a.css
.main {
width: 200px;
height: 400px;
margin-left: 100px;
position: relative;
border: 1px solid red;
}
.sub1 {
width: 100px;
height: 100px;
border: 1px solid;
position: absolute;
left: 0px;
}
.sub2 {
width: 50px;
height: 300px;
position: absolute;
top: 30px;
left: 20px;
border: 1px solid green;
}
now I want div.sub1 is relative to the parent div,
and div.sub2 is relative to the browser,
how can I set style to div.sub2?
As per my knowledge there are two possible solution either put second div outside the parent div. In this way .sub2 will not be child of parent div.
Or make second div position:fixed instead of absolute.
.sub2 {
width: 50px;
height: 300px;
position: fixed;
top: 30px;
left: 20px;
border: 1px solid green;
}
Fiddle
You need to set .sub1 position as relative (instead of absolute).
.sub1 {
width: 100px;
height: 100px;
border: 1px solid;
position: relative;
left: 0px;
}
I hope this helps.