I would like to get this style in CSS3:
CSS3 layout
For now, I have the simplest thing, the middle square with the following code:
HTML (pretty irrelevant, but I guess the tag does not need to be a div tag):
<div id="divBorder">
</div>
CSS:
#divBorder{
border-style: solid;
border-width: 1px;
position: absolute;
width: 300px;
height: 300px;
z-index: 15;
top: 50%;
left: 50%;
margin: -110px 0 0 -160px;
}
So, I just have basically centered the middle square in the center of the screen and that's all, I can't find a way to do the other two half squares on both sides of the full one.
I hope you can help me, thank you so much in advance!
You can achieve the desired layout with the following markup, using flexbox.
body {
margin: 0;
}
main {
display: flex;
flex-direction: column;
height: 100vh;
}
header {
flex: 1;
background-color: mediumspringgreen;
}
div {
flex: 4;
display: flex;
background-color: darkviolet;
}
section {
flex: 1;
}
section:nth-child(even) {
flex: 2;
background-color: darkorchid;
}
footer {
flex: 1;
background-color: deeppink;
}
<main>
<header></header>
<div>
<section></section>
<section></section>
<section></section>
</div>
<footer></footer>
</main>
.inner {
border:solid;
}
.outer {display: flex;
flex-direction:row;}
.side {width: 25%; height: 50px;}
.center {width: 50%; height: 50px}
<div class="outer">
<div class="side inner"></div>
<div class="center inner"></div>
<div class="side inner"></div>
</div>
You can use flexbox to do this. You can either set the width in procentage or you can look into sizing it with flexbox.
Related
My goal: A responsive navbar where the logo is always in the middle and an element
is always on the left. Depending on the context (page dependent), buttons can be
displayed in the right area or not.
My approach: I use a flexbox for the navbar. I have three divs in the flexbox. I have given all divs a fixed width. The middle box is also a flexbox. The div with a logo is located there. I position the logo on the right edge of the middle flexbox. The div with the logo has a fixed width (80px).
The problem: The approach works but I don't find this way very nice. Because the widths are dependent on each other. If you would change the logo and it would be wider or narrower then you would have to adjust the relative width of the middle and right box. The second problem is if the device smaller as 900px then this solution dont work.
Question: What other possibilities are there and what possibilities would resolve this "width" dependency?
#app {
margin: 0 auto;
max-width: 900px;
width:100%;
}
header {
height: 80px;
display: flex;
justify-content:space-between;
}
.header-left {
width:20%;
background: green;
}
.header-middle {
width:34%;
background: gray;
display: flex;
justify-content:flex-end;
}
.header-right {
width:46%;
background: green;
}
.logo {
background-color: red;
width:80px;
height: 80px;
text-align:center;font-size:70px;
}
<div id="app">
<small>width: 900px</small>
<header>
<div class="header-left">Burger Menu</div>
<div class="header-middle">
<div class="logo">
I
</div>
</div>
<div class="header-right">Context Buttons</div>
</header>
<div>
<div style="width:50%; background: black;color:white; text-align:center;">Controller Div 50%</div>
</div>
</div>
You can use flex-grow: 1 on the left and right elements, the middle element will be in center naturally. In this case, you don't need to set widths on elements.
#app {
margin: 0 auto;
max-width: 900px;
width:100%;
}
header {
height: 80px;
display: flex;
justify-content:space-between;
}
.header-left {
flex-grow: 1;
background: green;
}
.header-middle {
background: gray;
display: flex;
justify-content:flex-end;
}
.header-right {
flex-grow: 1;
background: green;
}
.logo {
background-color: red;
width:80px;
height: 80px;
text-align:center;font-size:70px;
}
<div id="app">
<small>width: 900px</small>
<header>
<div class="header-left">Burger Menu</div>
<div class="header-middle">
<div class="logo">
I
</div>
</div>
<div class="header-right">Context Buttons</div>
</header>
<div>
<div style="width:50%; background: black;color:white; text-align:center;">Controller Div 50%</div>
</div>
</div>
Since you're looking for different possibilities i'll suggest you to take the approch used by Tepken Vannkorn :
Centering brand logo in Bootstrap Navbar
Based on your comments, I would suggest the following code as a simple solution.
I have added a max-width value to your .logo CSS class and I have also moved your inline CSS from the front-end code, and created a .controller CSS class for it.
#app {
margin: 0 auto;
max-width: 900px;
width: 100%;
}
header {
height: 80px;
display: flex;
justify-content: space-between;
}
.header-left {
width: 20%;
background: green;
}
.header-middle {
width: 34%;
background: gray;
display: flex;
justify-content: flex-end;
}
.header-right {
width: 46%;
background: green;
}
.logo {
background-color: red;
width: 80px;
height: 80px;
text-align: center;
font-size: 70px;
max-width: 80px;
}
.controller {
width: 50%;
background: black;
color: white;
text-align: center;
}
<div id="app">
<small>width: 900px</small>
<header>
<div class="header-left">Burger Menu</div>
<div class="header-middle">
<div class="logo">
I
</div>
</div>
<div class="header-right">Context Buttons</div>
</header>
<div>
<div class="controller">Controller Div 50%</div>
</div>
</div>
A solution would be to use a mix of flex and position: absolute. Then you need only the left and the right container. the logo you can center with position left: left: calc(50% - calc(80px / 2));. The 80px is the width from your logo.
* {
margin: 0;
padding: 0;
}
#app {
margin: 0 auto;
max-width: 900px;
width:100%;
}
.header {
display: flex;
justify-content: space-between;
height: 80px;
background: yellow;
position: relative;
}
.header-left {
background-color: green;
width: 20%
}
.header-right {
background-color: green;
width: 44%;
}
.logo {
background-color: red;
width:80px;
height: 80px;
text-align:center;
font-size:70px;
position: absolute;
left: calc(50% - calc(80px / 2));
}
<div id="app">
<div class="header">
<div class="header-left">left</div>
<div class="logo">X</div>
<div class="header-right">right</div>
</div>
<div style="width:50%; background: black;">Controller Div 50%</div>
</div>
Using the following my .divider <div> is not showing. I guess this is because it is empty. If I add a "." in there, then I see it. Is it possible to make it 100% the height of the .wrapper without adding content?
.wrapper {
display: flex;
background-color: orange;
}
.left {
background-color: gray;
}
.divider {
background-color: green;
cursor: ew-resize;
width: 12px;
height: 100%;
}
.right {
flex-grow: 1;
background-color: yellow;
}
<div class="wrapper">
<div class="left">Left</div>
<div class="divider"></div>
<div class="right">Right</div>
</div>
https://jsfiddle.net/sub7fxk5/
Remove height: 100%; for .divider
.wrapper {
display: flex;
background-color: orange;
}
.left {
background-color: gray;
}
.divider {
background-color: green;
cursor: ew-resize;
width: 12px;
/* height: 100%; */
}
.right {
flex-grow: 1;
background-color: yellow;
}
<div class="wrapper">
<div class="left">Left</div>
<div class="divider"></div>
<div class="right">Right</div>
</div>
Removing the height and adding flex: 1 seems to help.
Is the result of the code below what you expect it to be?
The wrapper has no height, that means that setting a height to 100% would equal setting the height to 0.
the flex: 1 makes the item flexible even though it has no content and it shows.
Of course you can set a width too. So width: 12px would work. As would width: 100%; (which would push the left and right item to the other side)
You might also use a pseudo-element ::after as a divider. That would clean up your html a bit.
.wrapper {
display: flex;
background-color: orange;
}
.left {
background-color: gray;
}
.divider {
background-color: green;
cursor: ew-resize;
flex: 1;
}
.right {
flex-grow: 1;
background-color: yellow;
}
<div class="wrapper">
<div class="left">Left<br/><br/>Left</div>
<div class="divider"></div>
<div class="right">Right</div>
</div>
I have to create a layout which looks like:
I've prepared code like:
.red {
width: 50px;
height: 50px;
background-color: red;
margin-right: 20px;
}
.yellow {
width: 50px;
height: 50px;
background-color: yellow;
}
.blue {
width: 50px;
height: 50px;
background-color: blue;
justify-self: end;
}
.wrapper {
display: flex;
background-color: green;
width: 100%;
}
<div class="wrapper">
<div class="red"> </div>
<div class="yellow"> </div>
<div class="blue"> </div>
</div>
But this blue div don't want to align to the right side:
Here you can a have a preview of that:
https://jsfiddle.net/ncszob80/17/
I know that I can fix it with margin-left: auto css style for blue div.
But I'm wondering if there is some possibility of creating such layout only by using flex functionality.
So:
we can use only flex functionalities
there needs to be some margin between red div and yellow one
blue div needs to be at the very right
How to achieve that?
You wrote:
I know that I can fix it with margin-left: auto css style for blue div. But I'm wondering if there is some possibility of creating such layout only by using flex functionality.
Actually, margin-left: auto is flex functionality. It's a feature of flex layout.
From the flexbox specification:
ยง 8.1. Aligning with auto
margins
Also see:
In CSS Flexbox, why are there no "justify-items" and "justify-self" properties?
In summary, just use the auto margin. It's the cleanest, simplest and most efficient solution.
My best solution for you would be to change your DOM structure a little bit - but it accomplishes what you're looking for:
.left {
display: flex;
}
.red {
width: 50px;
height: 50px;
background-color: red;
margin-right: 20px;
}
.yellow {
width: 50px;
height: 50px;
background-color: yellow;
}
.blue {
width: 50px;
height: 50px;
background-color: blue;
}
.wrapper {
display: flex;
background-color: green;
width: 100%;
justify-content: space-between;
}
<div class="wrapper">
<div class="left">
<div class="red"> </div>
<div class="yellow"> </div>
</div>
<div class="right">
<div class="blue"> </div>
</div>
</div>
Basically, I wrapped your boxes in .left and .right, and then changed the .wrapper to justify-content: space-between so that the .right box is shoved to the right. Then, we make .left { display: flex; } to fix the issue with those boxes stacking without doing this, or changing the elements inside to display: inline; or display: inline-block;.
You can use nested flex boxes. Make the flex wrapper for your blue item and justify that to the end:
.wrapper {
display: flex;
background-color: green;
width: 100%;
}
.red {
width: 50px;
height: 50px;
background-color: red;
margin-right: 20px;
}
.yellow {
width: 50px;
height: 50px;
background-color: yellow;
}
.blueWrap {
width: 100%;
height: 50px;
display: flex;
justify-content: flex-end;
}
.blue {
width: 50px;
height: 50px;
background-color: blue;
}
<div class="wrapper">
<div class="red"> </div>
<div class="yellow"> </div>
<div class="blueWrap">
<div class="blue"></div>
</div>
</div>
Aside from changing your DOM structure or using the margin-left: auto fix CSS Grid is fantastic for this type of layout. I know you said only Flexbox but if you don't want any of the other solutions Grid might be a nice alternative. You can mix Flex functionality within the grid as well for finer control. I do this regularly to achieve the layout I'm in need of and it works well!
Happy coding!
Here is another idea if you don't want to consider margin:auto and without changing your html but like said in the accepted answer, margin is a feature of flexbox:
.red {
width: 50px;
height: 50px;
background-color: red;
margin-right: 20px;
}
.yellow {
width: 50px;
height: 50px;
background-color: yellow;
}
.blue {
width: 50px;
height: 50px;
background-color: blue;
order:1; /*make the blue the last element*/
}
.wrapper {
display: flex;
background-color: green;
width: 100%;
}
.wrapper:after {
content:"";
flex-grow:1; /*make this hidden element to take all the space and push the blue*/
}
<div class="wrapper">
<div class="red"> </div>
<div class="yellow"> </div>
<div class="blue"> </div>
</div>
Scenario :
I am having trouble getting an image to autofit a flexbox with a border around it. The image will be dynamically generated so sometimes the width or the height might be the longer side. Sometimes the image will be smaller or larger than the box it should be in, but it should automatically fit the size of the box and retain its proper proportions.
Tried Case :
The best I've come up with is to set both width and height of the image to 100%, and then use object-fit: contain.
However, object-fit: contain does not work well with borders. Instead of surrounding just the image the border is surrounding the entire parent div.
The Problem: If there is a tall skinny image it might enlarge or shrink to 30% width and 100% height. I would like the border to be also at the 30% and 100% region as well. However, the border is being placed at the 100% width and 100% height area which is not what I want.
What other method would work better for me here?
Here is a simplified look at my code:
<!DOCTYPE html>
<html>
<style>
html, body { width: 100%; height: 100% }
#outer {
width: 100%;
height: 100%;
display: flex;
background-color: green;
flex-direction: column
}
#top, #bottom {
flex: 1;
display: flex;
border: solid black 1px;
}
#first, #third {
flex: 1;
background-color: blue;
}
#second {
flex: 3;
background-color: yellow;
}
#second img {
border: solid black 5px;
object-fit: contain;
width: 100%;
height: 100%;
box-sizing: border-box;
}
</style>
<body>
<div id="outer">
<div id="top">
<div id="first">First</div>
<div id="second">
<img src="https://via.placeholder.com/350x800/faa">
</div>
<div id="third">Third</div>
</div>
<div id="bottom">
Bottom
</div>
</div>
</body>
</html>
If you run the above code snippet you will see the thick border is surrounding the entire parent region (shown in yellow), rather than just appearing around the image itself (pink area).
What can I do so that the border is only around the image itself?
Clarification
I need something that meets the following criteria:
Smaller images are scaled up to meet the size of the parent div
Larger images are scaled down to meet the size of the parent div
Images should be proportional (i.e. images must retain their aspect ratio and not become distorted)
The image should be centered within the parent div
The image should have a border only around the image and not the larger area
Code must work for both portrait and landscape images
In most cases only two sides of the image will touch the parent boundary, leaving the rest of the parent div empty (i.e. the yellow background in my code sample)
I'm actually quite surprised given how far CSS has come that there seems to be no simple solution for this.
Do you want only with height 100%? If not height 100% is depend on image's prop, you can use object-fit: fill; and height:auto;
<!DOCTYPE html>
<html>
<style>
html, body { width: 100%; height: 100% }
#outer {
width: 100%;
height: 100%;
display: flex;
background-color: green;
flex-direction: column
}
#top, #bottom {
flex: 1;
display: flex;
border: solid black 1px;
}
#first, #third {
flex: 1;
background-color: blue;
}
#second {
flex: 3;
background-color: yellow;
}
#second img {
border: solid black 5px;
object-fit: contain;
width: 100%;
height: auto;
box-sizing: border-box;
}
</style>
<body>
<div id="outer">
<div id="top">
<div id="first">First</div>
<div id="second">
<img src="https://picsum.photos/800/800">
</div>
<div id="third">Third</div>
</div>
<div id="bottom">
Bottom
</div>
</div>
</body>
</html>
Used object-fit: cover
so that the image will cover the entire parent.
Other solution will be inserting an image already having a border on it.Image can be edited online to attach a border to itself.
<!DOCTYPE html>
<html>
<style>
html, body { width: 100%; height: 100% }
#outer {
width: 100%;
height: 100%;
display: flex;
background-color: green;
flex-direction: column
}
#top, #bottom {
flex: 1;
display: flex;
border: solid black 1px;
}
#first, #third {
flex: 1;
background-color: blue;
}
#second {
flex: 3;
background-color: yellow;
}
#second img {
border: solid black 5px;
object-fit: cover;
width: 100%;
height: 100%;
box-sizing: border-box;
}
</style>
<body>
<div id="outer">
<div id="top">
<div id="first">First</div>
<div id="second">
<img src="https://via.placeholder.com/350x800/faa">
</div>
<div id="third">Third</div>
</div>
<div id="bottom">
Bottom
</div>
</div>
</body>
</html>
Updated Solution:
So, to achieve this, we can put image inside a container that will be
take height and width according to image. Put this image container div inside the main div container.
So, in this case, we have put the following code into #second conatiner, and adjusted the corresponding css to achieve the desired result.
html, body { width: 100%; height: 100% }
img {
max-width: 100%;
max-height: 100%;
width: auto;
height: auto;
transform: translate(-50%, -50%);
position: relative;
left: 50%;
top: 50%;
}
#testing {
display: inline-block;
/* text-align: center; */
}
#outer {
width: 100%;
height: 100%;
display: flex;
background-color: green;
flex-direction: column
}
#top, #bottom {
flex: 1;
display: flex;
border: solid black 1px;
}
#first, #third {
flex: 1;
background-color: blue;
}
#second {
flex: 3;
background-color: yellow;
display: flex;
margin: 0 auto;
justify-content: center;
}
#second img {
border: solid black 5px;
object-fit: contain;
box-sizing: border-box;
}
<!DOCTYPE html>
<html>
<body>
<div id="outer">
<div id="top">
<div id="first">First</div>
<div id="second">
<div id='testing'>
<img src="https://via.placeholder.com/1000x350/faa">
</div>
</div>
<div id="third">Third</div>
</div>
<div id="bottom">
Bottom
</div>
</div>
<div id="outer">
<div id="top">
<div id="first">First</div>
<div id="second">
<div id='testing'>
<img src="https://via.placeholder.com/350x1000/faa">
</div>
</div>
<div id="third">Third</div>
</div>
<div id="bottom">
Bottom
</div>
</div>
</body>
</html>
did you mean something like this?
changes are, move width: 100% and height: 100% to parent, add max-height: 100% on img, and add text-align: center on parent
update:
- add another div inside #second
- make #second display: flex; flex-direction: column; justify-content: center
- add max-width: 100% to img
- add max-height: 100%; max-width: 100%; height: fit-content; to the added div
html, body { width: 100%; height: 100% }
#outer {
width: 100%;
height: 100%;
display: flex;
background-color: green;
flex-direction: column
}
#top, #bottom {
flex: 1;
display: flex;
border: solid black 1px;
}
#first, #third {
flex: 1;
background-color: blue;
}
#second {
flex: 3;
background-color: yellow;
width: 100%;
height: 100%;
text-align:center;
display: flex;
flex-direction: column;
justify-content: center;
}
#second img {
border: solid black 5px;
box-sizing: border-box;
max-height: 100%;
max-width: 100%;
}
#vcenter{
max-height: 100%;
max-width: 100%;
height: fit-content;
}
<!DOCTYPE html>
<html>
<body>
<div id="outer">
<div id="top">
<div id="first">First</div>
<div id="second">
<div id="vcenter">
<img src="https://via.placeholder.com/350x800/faa">
</div>
</div>
<div id="third">Third</div>
</div>
<div id="bottom">
Bottom
</div>
</div>
</body>
</html>
same code for landscape images
html, body { width: 100%; height: 100% }
#outer {
width: 100%;
height: 100%;
display: flex;
background-color: green;
flex-direction: column
}
#top, #bottom {
flex: 1;
display: flex;
border: solid black 1px;
}
#first, #third {
flex: 1;
background-color: blue;
}
#second {
flex: 3;
background-color: yellow;
width: 100%;
height: 100%;
text-align:center;
display: flex;
flex-direction: column;
justify-content: center;
}
#second img {
border: solid black 5px;
box-sizing: border-box;
max-height: 100%;
max-width: 100%;
}
#vcenter{
max-height: 100%;
max-width: 100%;
height: fit-content;
}
<!DOCTYPE html>
<html>
<body>
<div id="outer">
<div id="top">
<div id="first">First</div>
<div id="second">
<div id="vcenter">
<img src="https://via.placeholder.com/1350x200/faa">
</div>
</div>
<div id="third">Third</div>
</div>
<div id="bottom">
Bottom
</div>
</div>
</body>
</html>
The subject says it all, but I am looking for a clean simple way to do this. Essentially think of it like this:
[A][__B_][A]
to
[A][A]
[__B_]
Hopefully that is clear enough but I can elaborate if need be.
Thanks in advance!
you can use flexbox order for that
.flex-container {
padding: 0;
margin: 0;
display: flex;
flex-flow: row wrap;
}
.flex-item {
box-sizing: border-box;
background: green;
padding: 20px;
width: 20%;
height: 100px;
border: 1px solid white;
color: white;
text-align: center;
}
#media screen and (max-width: 900px){
.flex-item {
background: green;
width: 50%;
height: 100px;
color: white;
text-align: center;
}
.flex-item:nth-of-type(2) {
order: 3;
width: 100%
}
}
<div class="flex-container">
<div class="flex-item">div a</div>
<div class="flex-item">div b</div>
<div class="flex-item">div a</div>
</div>
read more here: https://developer.mozilla.org/en/docs/Web/CSS/order
If you're starting with 3 elements in a row together, but you need element B to be outside on it's own, you will want to utilize flexbox.
You'd be focusing on the order property for the selectors, and using flex-grow on element B. Read through that document to get an idea on how to set that up, or to make sure that's exactly what you need. Otherwise, you can turn to jQuery.
You can do this by putting all three divs inside one div:
<div class="allthree">
<div class="twoas">
<div class="a"></div>
<div class="a"></div>
</div>
<div class="oneb">
<div class="b"></div>
</div>
</div>
Now add some CSS to this so the b is 100% width and the a is 50% width. Make sure the a is display: inline-block;
.allthree {
width: <your-width>
}
.allthree .twoas {
width: 100%;
}
.allthree .twoas .a {
display: inline-block;
width: 50%;
}
.allthree .oneb {
width: 100%;
}
.allthree .oneb .b {
width: 100%;
}