How to make a v-textarea fill the screen vertically? - css

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.

Related

Two column layout taking full screen but allowing one column to expand

I'm trying to create a somewhat complicated layout with two columns taking up the remaining height of their parent but where one of the two columns is able to exceed these bounds if its content requires it. (In my case, this is an image but I don't believe this matters).
Here's a picture of the desired result which I'm sure will explain much better what I'm looking after.
Note: Here the red border represents the screen bounds (100vw x 100vh).
Here's what I tried so far:
.container {
display: flex;
flex-direction: column;
height: 100vh;
}
.top {
background: orchid;
}
.columns {
flex: 1;
display: flex;
}
.columns>* {
flex: 1;
}
.left {
background: lightgreen;
/* Just make it larger than 100% */
height: calc(100% + 25px);
}
.right {
background: cornflowerblue;
}
<div class="container">
<div class="top">
Top Content
</div>
<div class="columns">
<div class="left">
Left Column
</div>
<div class="right">
Right Column
</div>
</div>
</div>
<div class="additional">
Additional Content
</div>
As you can see, the "additional content" section isn't pushed properly. This is because the left column is overflowing but isn't technically affecting its parent. I believe that if it did, then the right column wouldn't be sized properly. So this seems like two conflicting conditions and I'm not sure what to do.
Im not sure if this is the result you are looking for, but give it a try and let me know.
.container {
display: flex;
flex-direction: column;
height:max-content;
}
.top {
background: orchid;
}
.columns {
flex: 1;
display: flex;
}
.columns>* {
flex: 1;
}
.left {
background: lightgreen;
/* Just make it larger than 100% */
height: fit-content;
}
.right {
background: cornflowerblue;
max-height: 100vh;
}
First, the container is set to max-content, meaning that it will be as hight as the highes element inside it. Next, the right column is set to max-height:100vh, meaning that if your left column is not as high as 100vh, your container will be affected by that right column. As soon as left column exceeds 100vh mark of right column, the height:fit-content of left column makes its parent expand, leading to pushing the additional content properly while right column stays at 100vh.
In this case, if left column does not have enough content, it will get smaller then right column, if this is not desired behaviour, change the left-column height as you desire, but always us height properties that are affected by content (or min/max).

Responsive arrangement of divs with flexbox [duplicate]

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?

Flexbox wrapping issues [duplicate]

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?

Flexbox: how to get divs to fill up 100% of the container width without wrapping?

I'm in the process of updating an old inline-block-based grid model I have to a newer Flexbox one I created. Everything has worked fine, apart from one little snag, which has become a bit of a dealbreaker:
I have a bunch of CSS-controlled sliders; so there's a containing wrapper with 100% width, and inside is another div: its width is also 100%, but its white-space is set to nowrap. Using inline-block, this meant that the internal divs (which were also set to 100% width) wouldn't be bound by their parents' constraints and wrap onto the next line - they'd just carry on flowing out of the box. This is exactly what I wanted. However, I cannot get this to work at all with flexbox. For reference, here's an image:
And for reference, here's a jsFiddle of the thing working with inline-block: http://jsfiddle.net/5zzvqx4b/
...and not working with Flexbox: http://jsfiddle.net/5zzvqx4b/1/
I've tried all kinds of variations with flex, flex-basis, flex-wrap, flex-grow, etc. but for the life of me I can't get this to work.
Note that I can force it to do what I want in a hacky, inflexible way by setting the .boxcontainer width to 200%. That works for this single example, but in some cases I won't know beforehand how many child boxes there will be, and I'd rather not resort to inline styling on each element if possible.
To prevent the flex items from shrinking, set the flex shrink factor to 0:
The flex shrink factor determines how much the flex item will
shrink relative to the rest of the flex items in the flex
container when negative free space is distributed. When omitted, it is
set to 1.
.boxcontainer .box {
flex-shrink: 0;
}
* {
box-sizing: border-box;
}
.wrapper {
width: 200px;
background-color: #EEEEEE;
border: 2px solid #DDDDDD;
padding: 1rem;
}
.boxcontainer {
position: relative;
left: 0;
border: 2px solid #BDC3C7;
transition: all 0.4s ease;
display: flex;
}
.boxcontainer .box {
width: 100%;
padding: 1rem;
flex-shrink: 0;
}
.boxcontainer .box:first-child {
background-color: #F47983;
}
.boxcontainer .box:nth-child(2) {
background-color: #FABCC1;
}
#slidetrigger:checked ~ .wrapper .boxcontainer {
left: -100%;
}
#overflowtrigger:checked ~ .wrapper {
overflow: hidden;
}
<input type="checkbox" id="overflowtrigger" />
<label for="overflowtrigger">Hide overflow</label><br />
<input type="checkbox" id="slidetrigger" />
<label for="slidetrigger">Slide!</label>
<div class="wrapper">
<div class="boxcontainer">
<div class="box">
First bunch of content.
</div>
<div class="box">
Second load of content.
</div>
</div>
</div>
You can use the shorthand flex property and set it to
flex: 0 0 100%;
That's flex-grow, flex-shrink, and flex-basis in one line. Flex shrink was described above, flex grow is the opposite, and flex basis is the size of the container.
In my case, just using flex-shrink: 0 didn't work. But adding flex-grow: 1 to it worked.
.item {
flex-shrink: 0;
flex-grow: 1;
}
Set the flex-direction: column
You're trying to stack the items in a column rather than a row.
{
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}

flex-basis not working as expected

As i understand flex-basis is responsible for deciding the size of an element.
In the example below, I am trying to size all boxes equally to 100px.
Just using flex-basis is not achieving the effect.
.each_box {
-webkit-flex-grow: 0;
-webkit-flex-shrink: 0;
-webkit-flex-basis: 100px;
flex-grow: 0;
flex-shrink: 0;
flex-basis: 100px;
background-color: yellow;
height: 50px;
border: 1px solid black;
}
Plnkr here: http://plnkr.co/edit/LvrrzHWIw1tPGwK05bCU
I found I had to use min-width as well as flex-basis in Chrome. I'm not sure if I had another problem that caused this.
.flex-container {
display: flex;
width: 100%;
}
.flex-child {
flex-basis: 50%;
min-width: 50%;
}
Be sure to also add: flex-wrap: wrap; because the default value nowrap in order to fit everything in one line can affect the size of the elements (eg: width, flex-basis, etc..).
The flex-grow, flex-shrink, flex-basis properties only have an effect on elements in a flex container -- i.e. elements whose parent has display:flex.
You need to put your each_box divs directly inside of a display:flex element for them to honor their flex-related properties.
Specifically, your markup looks like this (from right clicking one of the yellow divs + hitting "inspect" in Firefox):
<div class="container">
<!-- ngRepeat: stock in stockList -->
<div class="ng-scope" ng-repeat="stock in stockList">
<div class="each_box ng-binding">
0-FB/100
You've got container styled as display:flex, but that does no good for your each_box elements, because they're grandchildren, separated from the flex container by the display:block ng-scope.
So you either need to get rid of the ng-scope wrapper, or make it also have display:flex.
Add a width: width:100px;
flex-basis gives a default proportion, which will then grow or shrink.
All works for me:
.flex-child { width:0; }
AND
.flex-child { min-width:0; }
AND
.flex-child { flex-shrink:0; } /* no scrollbars inside */

Resources