How to set the width of an element to take 100% the width of its parent minus an unknown width of sibling element.
index.html
<div class="main">
<div class="sidemenu">
...
</div>
<div class="contant">
...
</div>
</div>
style.css
.main
{
width: 100vw;
}
.sidemenu
{
width: X; /* this value is dymanic, it may change in runtime using JS */
}
.contant
{
width: ???; /* what do I put here? */
}
If the side-menu width was fixed I could of use calc(100% - X), but since the width is dynamic, how can I set the width to take the remaining width of the parent?
Can I achieve this using Css only (without JavaScript)?
You may use flexbox so there's no need to assign a specific width to the content area
e.g.
.main {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
}
.content { flex: 1; margin-left: 1rem; }
Codepen demo
I know this is an old post but this could also be done using css variables.
:root {
--dynamic-width: X;
}
.content {
width: CALC(100% - var(--dynamic-width));
}
See: https://jsfiddle.net/wzget15m/
the method you might look for is only possible using js otherwise you can't get the width of the element to calculate it with another.
Use display: flex in the main container:
.main {
display: flex;
}
.sidemenu {
width: X;
}
.contant {
width: 100%; /* what do I put here? */
}
Related
I'm using Vuetify and I want a page that is mostly one big v-textarea. There is some stuff on top, and maybe on the bottom, but besides that I want the page filled with v-textarea, with no scrolling (except scrolling inside the v-textarea). I feel adding a style like "height:calc(100vh - 100px)" is a bit hack.
Is there some way I can do this the real way?
Thanks.
Not sure what you call "the real way", but in one (more or less real) way or another you have to tell the <textarea> or one of its ancestors to fill up the free space of your viewport.
The typical solution is to have a parent wrapper which fills up the viewport, with display: flex; flex-direction: column and give your element flex-grow: 1
body {margin: 0; padding: 0; }
* { box-sizing: border-box; }
.wrapper {
min-height: 100vh;
display: flex;
flex-direction: column;
padding: 1rem;
}
.wrapper > * {
flex-grow: 0;
}
.wrapper > textarea {
flex-grow: 1;
margin-top: 1rem;
}
<div class="wrapper">
<div>
Some variable height stuff...
<hr>
<div contenteditable="true">Click to edit and make this element taller.<br> The textarea will adjust accordingly.</div>
</div>
<textarea>Your text area...</textarea>
</div>
The advantage is you don't have to hardcode the difference into <textarea>'s height. Instead, you tell it: fill up the available free space.
I have 3 divs inside a container. There are no nested divs.
I am using flex and order property.
On mobile, it is ok with order property.
But on larger screens it fails.
I did not use a container div for divs 2 and 3 in order to order them as 2,1,3 on mobile.
HTML FILE
<div class="container">
<div class="orange">1</div>
<div class="blue">2</div>
<div class="green">3</div>
</div>
CSS FILE
/*************** MOBILE *************/
.container
{
display: flex;
flex-wrap: wrap;
}
div.blue
{
order:1;
width: 100%;
}
div.orange
{
order:2;
width: 100%;
}
div.green
{
order:3;
width: 100%;
}
/***************************/
#media screen and (min-width:1200px)
{
.container
{
justify-content: space-between;
}
div.blue
{
order:2;
width: 36%;
}
div.orange
{
order:1;
width: 60%;
}
div.green
{
order:3;
width: 36%;
}
}
In your layout, using row wrap for the desktop view will be difficult, if not impossible, to implement with CSS. At a minimum, things would get overly complex. Why?
Because flexbox is not a grid system. It's a layout system designed to align content by distribution of space in the container.
In flexbox, items in a row wrap container must wrap to new rows. This means that div3 cannot wrap beneath div2. It must wrap beneath div1.
Here's how items wrap in a flex container with row wrap:
If div3 were to wrap under div2, that wouldn't be a row, that would be a grid, and flex items are confined to a straight, unbending row.
Put another way, you can't make a flex item wrap under another item in the same row.
As a result, white space created by items that aren't the tallest in the row is preserved in each column, creating unsightly gaps.
For your desired layout to work in row wrap, flex items would have to exit their row in order to close the gap – maybe with absolute positioning – which flexbox cannot do.
One way to align the items would be to wrap div2 and div3 in their own container. This new container would be a sibling to div1. It can then become a nested flex container with flex-direction: column. Now the gaps are gone and layout looks right.
Except, in this particular case, you need the order property to work (meaning all items must have the same parent), so a nested flex container is out of the question.
What may work is column wrap instead of row wrap:
/*************** MOBILE *************/
.container {
display: flex;
flex-direction: column;
height: 200px; /* necessary so items know where to wrap */
}
div.orange {
background-color: orange;
}
div.blue {
order: -1;
background-color: aqua;
}
div.green {
background-color: lightgreen;
}
.container > div {
width: 100%;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
/***************************/
#media screen and (min-width: 800px) {
.container {
flex-wrap: wrap;
}
div.orange {
flex-basis: 100%;
width: 50%;
}
div.blue {
flex-basis: 50%;
width: 50%;
order: 0;
}
div.green {
flex-basis: 50%;
width: 50%;
}
}
<div class="container">
<div class="orange">1</div>
<div class="blue">2</div>
<div class="green">3</div>
</div>
jsFiddle
Here are two other options:
Desandro Masonry
Masonry is a JavaScript grid layout library. It
works by placing elements in optimal position based on available
vertical space, sort of like a mason fitting stones in a wall.
source: http://masonry.desandro.com/
CSS Grid Layout Module Level 1
This CSS module defines a two-dimensional grid-based layout system, optimized for user interface design. In the grid layout model, the children of a grid container can be positioned into arbitrary slots in a predefined flexible or fixed-size layout grid.
source: https://drafts.csswg.org/css-grid/
Related post: Is it possible for flex items to align tightly to the items above them?
I have 3 divs inside a container. There are no nested divs.
I am using flex and order property.
On mobile, it is ok with order property.
But on larger screens it fails.
I did not use a container div for divs 2 and 3 in order to order them as 2,1,3 on mobile.
HTML FILE
<div class="container">
<div class="orange">1</div>
<div class="blue">2</div>
<div class="green">3</div>
</div>
CSS FILE
/*************** MOBILE *************/
.container
{
display: flex;
flex-wrap: wrap;
}
div.blue
{
order:1;
width: 100%;
}
div.orange
{
order:2;
width: 100%;
}
div.green
{
order:3;
width: 100%;
}
/***************************/
#media screen and (min-width:1200px)
{
.container
{
justify-content: space-between;
}
div.blue
{
order:2;
width: 36%;
}
div.orange
{
order:1;
width: 60%;
}
div.green
{
order:3;
width: 36%;
}
}
In your layout, using row wrap for the desktop view will be difficult, if not impossible, to implement with CSS. At a minimum, things would get overly complex. Why?
Because flexbox is not a grid system. It's a layout system designed to align content by distribution of space in the container.
In flexbox, items in a row wrap container must wrap to new rows. This means that div3 cannot wrap beneath div2. It must wrap beneath div1.
Here's how items wrap in a flex container with row wrap:
If div3 were to wrap under div2, that wouldn't be a row, that would be a grid, and flex items are confined to a straight, unbending row.
Put another way, you can't make a flex item wrap under another item in the same row.
As a result, white space created by items that aren't the tallest in the row is preserved in each column, creating unsightly gaps.
For your desired layout to work in row wrap, flex items would have to exit their row in order to close the gap – maybe with absolute positioning – which flexbox cannot do.
One way to align the items would be to wrap div2 and div3 in their own container. This new container would be a sibling to div1. It can then become a nested flex container with flex-direction: column. Now the gaps are gone and layout looks right.
Except, in this particular case, you need the order property to work (meaning all items must have the same parent), so a nested flex container is out of the question.
What may work is column wrap instead of row wrap:
/*************** MOBILE *************/
.container {
display: flex;
flex-direction: column;
height: 200px; /* necessary so items know where to wrap */
}
div.orange {
background-color: orange;
}
div.blue {
order: -1;
background-color: aqua;
}
div.green {
background-color: lightgreen;
}
.container > div {
width: 100%;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
/***************************/
#media screen and (min-width: 800px) {
.container {
flex-wrap: wrap;
}
div.orange {
flex-basis: 100%;
width: 50%;
}
div.blue {
flex-basis: 50%;
width: 50%;
order: 0;
}
div.green {
flex-basis: 50%;
width: 50%;
}
}
<div class="container">
<div class="orange">1</div>
<div class="blue">2</div>
<div class="green">3</div>
</div>
jsFiddle
Here are two other options:
Desandro Masonry
Masonry is a JavaScript grid layout library. It
works by placing elements in optimal position based on available
vertical space, sort of like a mason fitting stones in a wall.
source: http://masonry.desandro.com/
CSS Grid Layout Module Level 1
This CSS module defines a two-dimensional grid-based layout system, optimized for user interface design. In the grid layout model, the children of a grid container can be positioned into arbitrary slots in a predefined flexible or fixed-size layout grid.
source: https://drafts.csswg.org/css-grid/
Related post: Is it possible for flex items to align tightly to the items above them?
I have 3 divs inside a container. There are no nested divs.
I am using flex and order property.
On mobile, it is ok with order property.
But on larger screens it fails.
I did not use a container div for divs 2 and 3 in order to order them as 2,1,3 on mobile.
HTML FILE
<div class="container">
<div class="orange">1</div>
<div class="blue">2</div>
<div class="green">3</div>
</div>
CSS FILE
/*************** MOBILE *************/
.container
{
display: flex;
flex-wrap: wrap;
}
div.blue
{
order:1;
width: 100%;
}
div.orange
{
order:2;
width: 100%;
}
div.green
{
order:3;
width: 100%;
}
/***************************/
#media screen and (min-width:1200px)
{
.container
{
justify-content: space-between;
}
div.blue
{
order:2;
width: 36%;
}
div.orange
{
order:1;
width: 60%;
}
div.green
{
order:3;
width: 36%;
}
}
In your layout, using row wrap for the desktop view will be difficult, if not impossible, to implement with CSS. At a minimum, things would get overly complex. Why?
Because flexbox is not a grid system. It's a layout system designed to align content by distribution of space in the container.
In flexbox, items in a row wrap container must wrap to new rows. This means that div3 cannot wrap beneath div2. It must wrap beneath div1.
Here's how items wrap in a flex container with row wrap:
If div3 were to wrap under div2, that wouldn't be a row, that would be a grid, and flex items are confined to a straight, unbending row.
Put another way, you can't make a flex item wrap under another item in the same row.
As a result, white space created by items that aren't the tallest in the row is preserved in each column, creating unsightly gaps.
For your desired layout to work in row wrap, flex items would have to exit their row in order to close the gap – maybe with absolute positioning – which flexbox cannot do.
One way to align the items would be to wrap div2 and div3 in their own container. This new container would be a sibling to div1. It can then become a nested flex container with flex-direction: column. Now the gaps are gone and layout looks right.
Except, in this particular case, you need the order property to work (meaning all items must have the same parent), so a nested flex container is out of the question.
What may work is column wrap instead of row wrap:
/*************** MOBILE *************/
.container {
display: flex;
flex-direction: column;
height: 200px; /* necessary so items know where to wrap */
}
div.orange {
background-color: orange;
}
div.blue {
order: -1;
background-color: aqua;
}
div.green {
background-color: lightgreen;
}
.container > div {
width: 100%;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
/***************************/
#media screen and (min-width: 800px) {
.container {
flex-wrap: wrap;
}
div.orange {
flex-basis: 100%;
width: 50%;
}
div.blue {
flex-basis: 50%;
width: 50%;
order: 0;
}
div.green {
flex-basis: 50%;
width: 50%;
}
}
<div class="container">
<div class="orange">1</div>
<div class="blue">2</div>
<div class="green">3</div>
</div>
jsFiddle
Here are two other options:
Desandro Masonry
Masonry is a JavaScript grid layout library. It
works by placing elements in optimal position based on available
vertical space, sort of like a mason fitting stones in a wall.
source: http://masonry.desandro.com/
CSS Grid Layout Module Level 1
This CSS module defines a two-dimensional grid-based layout system, optimized for user interface design. In the grid layout model, the children of a grid container can be positioned into arbitrary slots in a predefined flexible or fixed-size layout grid.
source: https://drafts.csswg.org/css-grid/
Related post: Is it possible for flex items to align tightly to the items above them?
To center items with display: block people use margins: auto. If I set max-width to child that needs to be centered and there's enough space around it will fluid as much to max-width as it needs to (depending on its content). But if I change display property of parent element to flex it doesn't take all free space anymore. I really need to use max-width since I want element to shrink on small screens.
Here's the jsfiddle . Clicking on the button swaps display: flex to display: block on parent. I want the green space on flex to fluid as much as it's possible for max-width as it's done with display:block
EDIT:
I also would like to use flex-direction: column
$('input').click(function() {
var curDisplay = $('#parent').css('display');
if (curDisplay == 'block') {
$('#parent').css('display', 'flex');
$('input').val('flex');
} else {
$('#parent').css('display', 'block');
$('input').val('block');
}
})
#parent {
display: flex;
flex-direction: column;
width: 100%;
background-color: red;
height: 50px;
}
#child {
max-width: 300px;
background-color: green;
height: 50px;
margin: auto;
}
input {
width: 100%:
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent">
<div id="child">
<input type="button" value="Click Me!" />
</div>
</div>
I think you're looking for flex-basis. By using a % you can get very close. You can use px to set the initial width, it will still be "responsive" until you hit the minimum width if you have it set.
on the child element:
div {
flex-basis:40%;
}
Here is the W3
Why not just set the width of the child to 100%? If you need to center the button in the child you can simply add:
display: flex;
justify-content: center;
Also remove width: 100% from the input.