Overlapping flex boxes or a different approach? - html

I'm looking for advice on how to approach the layout as shown in this image.
I'm not sure if flex alone can handle the overlapping green dotted boxes (using a transform?) or if the blocks should be flex boxes and the green dotted overlapping boxes should just be relatively positioned divs? The mobile version is fairly straight-forward as there's no overlapping involved but I'm unsure how to 'slice' the design up so the CSS can handle both situations.
Below is an initial attempt using transform: scale.
.flex-box-row {
display: flex;
justify-content: space-between;
}
.flex-box-row-box {
border: 1px dashed red;
width: 30%;
text-align: center;
min-height: 200px;
}
.flex-box-dots {
max-height: 50px;
border: 1px dashed green;
transform: scale(1.5, 1);
}
.flex-box-dots::after {
content: "..................";
letter-spacing: 4px;
font-size: 18px;
color: black;
margin-left: 10px;
}
<div class="flex-box-row">
<div class="flex-box-row-box">
BLOCK 1
</div>
<div class="flex-box-dots"></div>
<div class="flex-box-row-box">
BLOCK 2
</div>
<div class="flex-box-dots"></div>
<div class="flex-box-row-box">
BLOCK 3
</div>
</div>

You can get the overlapping effect by using negative margin! Here's an example:
.container {
display: flex;
}
.red {
width: 100px;
height: 100px;
border: 2px dotted red;
}
.green {
width: 150px;
height: 20px;
border: 2px dotted green;
margin: 0 -30px;
background-color: white;
z-index: 1;
}
#media (max-width: 500px) {
.container {
flex-direction: column;
align-items: center;
}
.green {
width: 20px;
height: 150px;
margin: 0;
}
}
<div class="container">
<div class="red"></div>
<div class="green"></div>
<div class="red"></div>
<div class="green"></div>
<div class="red"></div>
</div>

Related

Container not fitting to screen and flex-direction: row not working properly

I'm starting out an application in angular and really struggling getting a basic layout setup; I have experience with angular but actual html/css design is completely new to me
Nothing I've tried seems to allow this container to take up the entirety of the screen. I have tried using multiple different settings on the html and container css classes and nothing will actually fit the container to the screen with width; but the height always seems to fit properly.
Aside from this flex-direction: row does not seem to consistently work. For example, I am trying to get the div "side" and the div "main" inside of the header div to fit next to each-other. Instead of this, those div's act like columns; despite the fact I have nowrap on; I have also tried display: inline-block and that also does not work. I have decreased the width of side and main in hopes that they would then fit next to eachother and that also does not work.
Screenshot:
Full View
html {
height: 100vh;
width: 100vw;
margin: 0;
padding: 0;
}
.container {
position: relative;
top: 0;
left: 0;
bottom: 0;
right: 0;
border: 1px solid black;
display: flex;
flex-direction: column;
}
.header {
margin-top: 15px;
border: 1px solid red;
height: 15vh;
flex-direction: row;
flex-wrap: nowrap;
}
.body {
border;
1px solid green;
height: 80vh;
}
.side {
width: 15vw;
border: 1px solid yellow;
}
.main {
width: 50vw;
border: 1px solid blue;
}
<div class="container">
<div class="header">
<div class="side">
<p>HI</p>
<div class="main">
<p>HI2</p>
</div>
</div>
<div class="body">
<p>I am the body</p>
</div>
</div>
</div>
Firstly - there are quite a few typos in your code. You haven't closed the side class or the main class and there is no closing div for the side div.
Secondly - After I'd tidied up your code, I noticed that you were making the .container display: flex; when in fact you needed to make the .header display: flex; as this is the parent of the side and main divs.
This is a great guide for flexbox: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
This should work for you:
html {
height: 100vh;
width: 100vw;
margin: 0;
padding: 0;
}
.container {
position: relative;
top: 0;
left: 0;
bottom: 0;
right: 0;
border: 1px solid black;
display: flex;
flex-direction: column;
}
.header {
margin-top: 15px;
border: 1px solid red;
height: 15vh;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
}
.side {
width: 15vw;
border: 1px solid yellow;
}
.main {
width: 50vw;
border: 1px solid blue;
}
.body {
border: 1px solid green;
height: 80vh;
}
<div class="container">
<div class="header">
<div class="side">
<p>HI</p>
</div>
<div class="main">
<p>HI2</p>
</div>
</div>
<div class="body">
<p>I am the body</p>
</div>
</div>
main is inside side. if you want them to be beside each other, you will need to arrange them as siblings within the flexbox.
you also forgot to add display: flex on the header css.
try this
html {
height: 100vh;
width: 100vw;
margin: 0;
padding: 0;
}
.container {
position: relative;
top: 0;
left: 0;
bottom: 0;
right: 0;
border: 1px solid black;
display: flex;
flex-direction: column;
}
.header {
margin-top: 15px;
border: 1px solid red;
height: 15vh;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.body {
border: 1px solid green;
height: 80vh;
}
.side {
width: 15vw;
border: 1px solid yellow;
}
.main {
width: 50vw;
border: 1px solid blue;
}
<div class="container">
<div class="header">
<div class="side">
<p>HI</p>
</div>
<div class="main">
<p>HI2</p>
</div>
</div>
<div class="body">
<p>I am the body</p>
</div>
</div>

Creating overlays in CSS

I am trying to create an overlay similar to this image but can't seem to figure it out.
I tried using the absolute positioning but it doesn't seem to work for more than 1 child element.
Any way around this, please?
body, html {
height: 100%;
}
body {
display: flex;
justify-content: center;
align-items: center;
}
.parent {
border: 2px solid #0074d9;
color: #0074d9;
padding: 20px;
width: 100%;
}
.element {
border: 1px dotted #000;
background-color: #eee;
padding: 20px;
color: #000;
position: absolute;
width: 40%;
}
.element2 {
border: 1px dotted #000;
background-color: #eee;
padding: 20px;
color: #000;
position: absolute;
width: 40%;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div class="parent">
Parent element
<div class="element">Child element</div>
<div class="element2">Second Child element</div>
</div>
</body>
</html>
Here's a brief take on it.
I set the main container to position: relative;, so that any position: absolute; children are positioned relatively to the parent.
I make a child-container to hold all the children, and place it at the bottom (and slightly extending out of) the main container, by doing top: 100%; combined with transform: translateY(-50%);. This also has display: flex; on it, so that its children will align themselves side-by-side.
You can add or remove children as necessary and it will automatically accommodate.
.container {
position: relative;
height: 125px;
background-color: #42b6f4;
}
.container>.main-text {
padding: 20px;
color: white;
font-family: Arial;
font-size: 24px;
}
.child-container {
position: absolute;
display: flex;
justify-content: space-between;
width: 100%;
top: 100%;
left: 50%;
transform: translateY(-50%) translateX(-50%);
}
.child-container > .child {
flex-grow: 1; /* Children should grow to fill unoccupied space */
padding: 20px;
margin: 20px; /* Amount of space between children */
border: 1px solid #ccc;
background-color: white;
border-radius: 5px;
}
<div class="container">
<div class="main-text">This is some main text</div>
<div class="child-container">
<div class="child">Child 1</div>
<div class="child">Child 2</div>
</div>
</div>
Below is a version with borders on all elements, as to explain the concept a bit.
.container {
position: relative;
height: 125px;
border: 2px solid red;
margin-bottom: 60px;
}
.container>.main-text {
padding: 20px;
color: white;
font-family: Arial;
font-size: 24px;
}
.child-container {
position: absolute;
display: flex;
justify-content: space-between;
top: 100%;
left: 50%;
width: 100%;
transform: translateY(-50%) translateX(-50%);
border: 2px dotted green;
}
.child-container > .child {
flex-grow: 1; /* Children should grow to fill unoccupied space */
padding: 20px;
margin: 20px; /* Amount of space between children */
border: 2px dashed blue;
border-radius: 5px;
}
<div class="container">
<div class="main-text">This is some main text</div>
<div class="child-container">
<div class="child"></div>
<div class="child"></div>
</div>
</div>
<span style="color: red;">Parent Container</span><br>
<span style="color: green; margin-left: 15px;">Child Container</span><br>
<span style="color: blue; margin-left: 30px;">Child</span>
Your second child element is on top of the first child element.
1) Add position : relative to parent element
2) You have to use top, bottom, left, right css attributes to place your children elements wherever you want.
body, html {
height: 100%;
}
body {
display: flex;
justify-content: center;
align-items: center;
}
.parent {
border: 2px solid #0074d9;
color: #0074d9;
padding: 20px;
width: 100%;
position : relative;
}
.element {
border: 1px dotted #000;
background-color: #eee;
padding: 20px;
color: #000;
position: absolute;
width: 40%;
top : 20;
right : 0;
}
.element2 {
border: 1px dotted #000;
background-color: #eee;
padding: 20px;
color: #000;
position: absolute;
width: 40%;
top : 20;
left : 20;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div class="parent">
Parent element
<div class="element">Child element</div>
<div class="element2">Second Child element</div>
</div>
</body>
</html>

How to reduce unnecessary space in div with wrapped word

I have a small div with fixed width and height, inside i have text, that could be probably wrapped and icon
All i need is to keep icon as close as possible to text, but if text is wrapped it will have extra space inside it
Example at JsFiddle
HTML
<div class="wrapper">
<div class="title">
Total elements
</div>
<div class="icon"></div>
</div>
Css
wrapper {
display: flex;
align-items: center;
justify-content: flex-start;
height: 50px;
width: 100px;
}
.title {
border: 1px solid green;
}
.icon {
border: 1px solid red;
width: 8px;
height: 8px;
}
You can use CSS Grid system:
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr;
grid-column-gap: 0em;
height: 50px;
width: 100px;
}
SOLUTION 1:
Well. To answer your question, you can straight ahead apply width to the .title.
.wrapper {
display: flex;
align-items: center;
justify-content: flex-start;
height: 50px;
width: 100px;
}
.title {
border: 1px solid green;
width: 58px;
}
.icon {
border: 1px solid red;
width: 8px;
height: 8px;
}
<div class="wrapper">
<div class="title">
Total elements
</div>
<div class="icon"></div>
</div>
SOLUTION 2:
But I would suggest that you use float instead of flex model with the below solution
.wrapper {
height: 50px;
font-size: 0px;
}
.title {
border: 1px solid green;
height: 50px;
line-height: 50px;
}
.icon {
border: 1px solid red;
width: 8px;
height: 8px;
}
.title, .icon {
display: inline-block;
vertical-align: middle;
font-size: 16px;
}
<div class="wrapper">
<div class="title">
Total elements
</div>
<div class="icon"></div>
</div>
<div class="wrapper">
<div class="title">
Total elements
</div>
<div class="icon"></div>
</div>
<style type="text/css">
.wrapper
{
}
.title {
border: 1px solid green;
display: inline-block;
max-width: 60px;
vertical-align: middle;
}
.icon
{
border: 1px solid red;
width: 8px;
height: 8px;
display: inline-block;
}
</style>

How to center inline-block element with margin

HTML:
<div id="wrap">
<div id="block1"></div>
<div id="block2"></div>
</div>
CSS:
div#wrap{
margin-top: 3em;
border: solid 1px black;
text-align: center;
}
div#wrap *{
display: inline-block;
width: 12.5em;
margin-top: 1em;
height: 8em;
}
div#wrap *:not(:last-child){
margin-right: 8em;
}
#block1{
background: orange;
}
div#wrap #block2{
background: magenta;
}
These 2 blocks are supposed to be centered in responsive design mode. When the screen is wide enough to have 2 blocks in a row, the code works. But when I narrow the screen down, the top block is shifted to the left because of the margin:
fiddle
Is it possible to fix this without media queries?
Edit
I tried flex-box:
div#wrap{
margin-top: 3em;
border: solid 1px black;
display: flex;
flex-flow: row wrap;
justify-content: center;
}
fiddle2
A solution is to use flex and justify-content:space-around and remove margin:
div#wrap {
margin-top: 3em;
border: solid 1px black;
justify-content:space-around;
display: flex;
flex-wrap: wrap;
}
div#wrap * {
display: inline-block;
width: 12.5em;
margin-top: 1em;
height: 8em;
}
#block1 {
background: orange;
}
#block2 {
background: magenta;
}
<div id="wrap">
<div id="block1"></div>
<div id="block2"></div>
</div>
If you use a container with negative margin, you don't need to vary the margin for the endpoints of the rows at different breakpoints and you can just go with inline-block. I set font-size to zero in the container so I can calculate my widths using percents without worrying about white space.
div#wrap {
margin-top: 3em;
border: solid 1px black;
padding: 20px;
text-align: center;
}
.block {
display: inline-block;
width: 12.5em;
margin: 20px;
height: 8em;
font-size: 16px;
}
.block-container {
margin: -20px;
font-size: 0;
}
#block1 {
background: orange;
}
#block2 {
background: magenta;
}
<div id="wrap">
<div class="block-container">
<div class="block" id="block1"></div>
<div class="block" id="block2"></div>
</div>
</div>

Flexbox row pushing columns down

I've been using flex layouts for a while now.
mainly the holy grail type layout and it works well.
Today decided to try create the same thing to help me learn more about flexbox.
but using columns on the right side for sidebar area, and rows as the logo/heading and page div's.
I've put this in a codepen so you can see the markup code yourself.
my issue is the logo/heading and main page when set to row pushes the columns downwards.
<div class="wrapper">
<div class="nav">logo content and site banner goes here
<div class="spacer">
</div>
<div class="content">main page content goes here</div>
</div>
<div class="one">page index goes here</div>
<div class="two">twitter logo goes here</div>
<div class="three">chatbox goes here</div>
</div>
div {
box-sizing: border-box;
}
.wrapper {
border: 2px solid blue;
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: flex-end;
position: relative;
}
.nav {
flex-direction: row;
border: 2px solid green;
width: 100%;
height: 100px;
align-self: flex-start;
padding-left: 8px;
margin-bottom: 4px;
}
.spacer {
height: 140px;
width: 100%;
}
.content {
flex-direction: row;
border: 2px solid green;
height: 40px;
padding-left: 8px;
align-self: flex-start;
}
.one {
width: 200px;
height: 200px;
border: 2px solid red;
flex-grow: 0;
padding: 8px;
}
.two {
width: 200px;
height: 200px;
border: 2px solid red;
flex-grow: 0;
padding: 8px;
}
.three {
width: 200px;
height: 200px;
border: 2px solid red;
flex-grow: 0;
padding: 8px;
}
https://codepen.io/anon/pen/GmZWvp
even if setting the width to something smaller before it even reaches the columns
the block pushes the columns, down, how could i do this where it doesn't effect the column on the right?
I know i could position: absolute the main page div, or create a nested div in logo/heading
and give it height of say 120px; to get it to go below the logo heading.
But there must be a way of putting a row next to a column without it pushing the column down.
since the div/row for the logo heading/main page is a block element.
If you know how to do this please let me know what to change, where and why etc.
Again this isn't for production, it's just to see if I can solve this quirky puzzle.
First, even if you set display: flex on the wrapper, you can't set flex-direction: row (or column) on its children to change their direction. The flex-direction property should be set on the flex container, in this case the wrapper. If you want to change direction on flex items belonging to one flex container, you need to wrap them and make that nested wrapper be both a flex item and a flex container, here done with the side wrapper in my first sample
If you rearrange your markup a little, you can get this
div {
box-sizing: border-box;
}
.wrapper {
border: 2px solid blue;
display: flex;
}
.nav {
border: 2px solid green;
width: 100%;
height: 100px;
padding-left: 8px;
margin-bottom: 4px;
}
.content {
flex: 1;
border: 2px solid green;
height: 40px;
padding-left: 8px;
}
.side {
width: 200px;
}
.one {
height: 200px;
border: 2px solid red;
padding: 8px;
}
.two {
height: 200px;
border: 2px solid red;
padding: 8px;
}
.three {
height: 200px;
border: 2px solid red;
padding: 8px;
}
<div class="nav">logo and site banner goes here</div>
<div class="wrapper">
<div class="content">main page content goes here</div>
<div class="side">
<div class="one">page index goes here</div>
<div class="two">twitter logo goes here</div>
<div class="three">chatbox goes here</div>
</div>
</div>
If you can't, or don't want, to change markup, then you need to combine flexbox with absolute positioning.
div {
box-sizing: border-box;
}
.wrapper {
position: relative;
display: flex;
flex-direction: column;
}
.nav {
border: 2px solid green;
width: 100%;
height: 100px;
padding-left: 8px;
margin-bottom: 4px;
}
.content {
width: calc(100% - 200px);
border: 2px solid green;
height: 40px;
padding-left: 8px;
}
.one, .two, .three {
position: absolute;
right: 0;
width: 200px;
height: 200px;
border: 2px solid red;
padding: 8px;
}
.one {
top: 104px;
}
.two {
top: 304px;
}
.three {
top: 504px;
}
<div class="wrapper">
<div class="nav">logo and site banner goes here</div>
<div class="content">main page content goes here</div>
<div class="one">page index goes here</div>
<div class="two">twitter logo goes here</div>
<div class="three">chatbox goes here</div>
</div>