Fluidly vertically expanding DIV or TEXTAREA - css

I want a textarea to take up as much vertical space as possible without overlapping any other visual elements. Obviously different screens / devices are different heights so I need the solution to be fluid (I think that's the right term).
The other questions I've looked at don't involve textareas, instead using (child) DIVs whose content is already determined. I don't need the textarea to expand dynamically to fit it's content, I just want it to be as tall as possible but without obscuring any other elements.
I've collected together parts of answers to similar questions but can't quite make it work:
http://jsfiddle.net/wa5zU/
CSS:
body, html {
height:100%
}
p {
text-align:justify
}
textarea {
resize:vertical;
height:auto;
width:100%;
box-sizing:border-box;
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
}
.vexpand {
border:1px solid blue
}
.vexpand {
position:absolute;
bottom:0;
width:90%;
height:auto
}
HTML:
<h2>Some content of variable length / height to fill the top portion of the screen</h2>
<p>Either: 1) make the blue-bordered DIV expand fluidly to fill this gap or 2) make the textarea expand to achieve the same effect</p>
<div class="vexpand">
<div>One line of content related to the textarea that must be kept with the textarea</div>
<textarea rows=5 cols=10>I have heard that textareas need valid rows and cols attributes in order to respond correctly to height and width css</textarea>
</div>
This attempt is based on position:absolute and bottom:0 assuming that the DIV can be expanded upwards. I did it this way because the content above the DIV/TEXTAREA is variable so couldn't find an elegant and robust way to measure from the top.
There is a line of content related to the textarea that must be kept with the textarea, hence encapsulating this content and the textarea in a div. Ideally I would prefer that content to stay above the textarea.
Things I've tried / seen in related questions:
position:absolute and conflicting absolute position
setting the height of body and html to 100% so that CSS can perform calculations
using height:auto or height:100% on the wrapper div .vexpand or the textarea
setting the cols and rows attributes on the textarea so that it responds to height and width

Is this what you want to do?
http://jsfiddle.net/wa5zU/2/
body, html {
height:100%;
margin: 0;
padding: 0;
}
p {
text-align:justify
}
*
{
box-sizing:border-box;
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
}
textarea {
resize:vertical;
height: calc(100% - 20px) ;
width:100%;
}
.text-content
{
height: 80%;
overflow: auto;
padding: 10px;
}
.editor
{
height: 20%;
overflow: hidden;
padding: 10px;
}

Related

Two divs inside another div and slide left right

I have a div that is masked off in terms of its width. Inside, I have 2 divs of the same width floated, so 100% + 100%. This means that either the left is visible or the right is visible at any one time.
In fact, what I'm trying to achieve is almost exactly the same as this:
jquery slide div within a div
Just one difference though. The height of my parent isn't fixed, it's dependent on the child size. So when I apply position: absolute; to the parent, it all goes pear-shaped.
Any solutions to this? I can use flexbox if necessary as I don't support IE8/9.
CSS would be something like this
.outer-wrap {
overflow:hidden;
position:relative;
width:300px;
}
.middle-wrap {
overflow:hidden;
position:absolute; // this doesn't work because it has no fixed height
left:0;
width:600px;
}
.middle-wrap.open {
right:0;
}
.inner-wrap {
float:left;
width:300px;
}
HTML
<div class="outer-wrap">
<div class="middle-wrap">
<div class="inner-wrap"></div>
<div class="inner-wrap"></div>
</div>
</div>
Another edit: I created a codepen, it's here: http://codepen.io/anon/pen/oxwmex CLick on the two buttons on the far right, they switch between the states
As you noted, your solution doesn't work because .middle-wrap has no fixed height. Try it with the following settings (note: no floats, no absolute positions):
.outer-wrap {
overflow-x: hidden;
position: relative;
border: 1px solid red;
width: 300px;
margin: 0 auto;
}
.middle-wrap {
position: relative;
width: 600px;
left: 0px;
}
.inner-wrap {
display: inline-block;
width: 300px;
vertical-align: top;
}
This will display the left of the two .inner-wraps within the visible part of .outer-wrap. To make the right .inner-wrap visible apply something like
jQuery(".middle-wrap").css("left", "-300px")
to the element or event you use for switching between the two inner-wraps. Or if you want it animated:
jQuery(".middle-wrap").aminmate({left: "-300px"})
(Plus another method to switch back to left: 0px)
The heigth of all elements is automatically adjusted to the heigth of the higher of the two .inner-wrap elements.
P.S. (edit): Erase the style="height:100px;" settings from the inner-wraps in the HTML, just fill them with some content to see it working.

CSS: Auto stretch div to fit available horizontal space

How can I style a div with CSS to automatically fit in a gap? At the moment, I have something like this
HTML
<div id="wrapper">
<div id="auto-width"></div>
<div id="changing-width"></div>
</div>
CSS
#wrapper {
padding: 30px;
}
#wrapper * {
height: 50px;
display: inline-block;
}
#auto-width {
width: 271px; /*I don't want to have to set this value*/
}
#changing-width {
width: 140px;
float: right;
margin-left: 30px;
}
I want the div with the ID "auto-width" to change it's width based on the padding of the wrapper, and the width and margin of the "changing-width" div. I don't mind using the padding and margin values, but in my actual project, the width of the "changing-width" div actually changes depending on the amount text in it and I want to "auto-width" div to change with it.
JSFiddle example:
https://jsfiddle.net/bve8162f/
If the width of the right div is fixed, then you could set the width of the left div like so:
#auto-width {
width: calc(100% - 200px);
}
...where the 200px is the width of your right div plus the padding. If you're using a css preprocessor like Less or Sass, you could create a variable so you can define the value in one place for both styles.
Note that the 100% refers to the explicit width of the parent. This solution seemed to work in your fiddle (updated version here,) but if your production code is set up a little differently, this may not work. I'll see if I can stumble across a different way, but this is one method I personally like to use when I can.

Why isn't <body> expanding to fit its contents?

I have a table that extends off the edge of the screen, but the body only gets as wide as the screen, causing the table to overflow it.
Demo: http://jsfiddle.net/6REkj/
<html>
<head>
<style>
table { background-color: lime; }
body { border: 2px solid blue; }
</style>
</head>
<body>
<table>
<tr><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td></tr>
</table>
</body>
</html>
This is one of those things that make me think CSS is broken. I thought containing elements were supposed to expand to fit their contents.
Question 1: Why is it doing that?
Question 2: What should I do to get a margin between the table and the right edge of the page?
if you set display:table; to body or html, it will allow to grow its width over the 100% of viewport. it will just expand like a table does :)
html {display:table;width:100%; /* need to set a width to 100%, wich means here a min-width since it is displayed with the same specifities thas has a table , it shrinks and expand according to its content */}
http://jsfiddle.net/6REkj/1/
other options :
display:inline-block;min-width:100%; on body : http://jsfiddle.net/6REkj/3/
position:absolute;min-width:100%; on html : http://jsfiddle.net/6REkj/4/
Edit nowdays, min-width:max-content would do . http://jsfiddle.net/bj4wk6m2/
It's very strange that the simplest solution hasn't been mentioned:
body {
width: fit-content;
min-width: 100%; /* because the content might only be a few words */
box-sizing: border-box; /* because 100% + padding > 100% */
}
Unfortunately that doesn't work everywhere and it still requires prefixing. In Chrome (with Blink these days) that would be: -webkit-fit-content (-webkit- in Blink, weird).
CSS isn't broken, the behaviour you are seeing is by design.
Some quotes from the link above:
The following constraints must hold among the used values of the other properties:
'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block
..
If 'width' is set to 'auto', any other 'auto' values become '0' and 'width' follows from the resulting equality.
From this I understand that block level elements have a default width of 100% of their containing block if all of the other properties are not set.
<body> is by default a block level element.
You could set float: left; or display: inline-block on body and it will grow with its content.
Here's a jsFiddle.
To answer question 2 (to get the result of the accepted answer without resorting to setting display: table on an element which isn't a table), you could do it this way:
CSS:
html {
padding: 10px;
}
html, body {
margin: 0px;
}
body {
border: 2px solid blue;
display: inline-block;
min-width: 100%;
box-sizing: border-box;
}
table, p {
background-color: cyan;
}
Here's a jsFiddle.
The only solution for this is to have a vertical scrollbar.
It can be achieved with an additional div, wrapping the table.
This would be the css:
body { border: 2px solid blue; }
table, p { background-color: cyan; width: 100%; word-wrap:break-word;}
div { width: 100%; overflow-x: auto;}
If you would only have the p-Tag, the attribute word-wrap:break-word; helps.
You can also move the paragraph outside the div, which allows you to see the whole content without scrolling.
See the fiddle for a working sulution:
http://jsfiddle.net/WrbpJ/
If you prefer scrolling the whole page, and not only the div, this can be used:
body { border: 2px solid blue; display: table;}
See http://jsfiddle.net/sGH4t/
If you don't want the scrollbar at all, you'll have to use lists or divs instead of a table.
The way you have used tr and td tags, the data in table is bound to overflow.
You have to decide how many rows and colmuns your table should have, when you are using simple html table. just put tr and td tags accordingly, and then you are done.http://jsfiddle.net/6REkj/Fiddle

How do I set the height of a div nested inside a float to be relative to window height?

I'm trying to build the simple layout that I have got in the image below. (1),(2) and (3) are required content panes - (4) I'm not sure if I need for positioning.
My main problem is that the height of (1) needs to be set relatively to be 75% of window (viewport) height. Below it, I want to have content added separately, that can have variable height. And on the right, I want a single independent column of content with variable height.
I think I need to put (1) and (2) into (4) to let them float together to the left of (3) properly. But if I do that, I can't set the height of (1) to 75% because it's now relative to (4), which as a float, has zero height. But if I then set (4) to 100% height of window, that will cause problems when content in (3) grows.
What am I missing?
Ps. It's important that (1) has a fluid height and is always 75% of the current viewport height - otherwise I could have set it via javascript on load. I could technically extend this to resize the window procedurally whenever the window height is changed, but there should be a more elegant CSS way to do this.
A pure CSS solution requires that there's no border around (4), the left column, because we need to give it height:100% but allow overflow:visible so that (2), the bottom left pane, isn't cut off.
html, body {
height: 100%;
}
#cont1, #cont2 {
width: 45%; /* or something less than 50% */
float: left;
}
#cont1 {
height: 100%;
overflow: visible;
}
#sub1 {
height: 75%;
}​
http://jsfiddle.net/tMUMj/3/
However, using JavaScript to resize the left top pane isn't as inelegant as you might think. Using jQuery:
$(document).ready(function() {
$(window).trigger('resize');
});
$(window).on('resize',function() {
$('div#lefttoppane').height( 0.75 * $(window).height() );
});
http://jsfiddle.net/tMUMj/
The computation itself is now restricted to one line of code, plus two event handlers, one of which triggers the other.
You can only use float on the right container and set the width of the left one to let's say (50%). If you right container takes 50% total (border, padding and margin included), it will float on its right.
I think this is what you mean:
<div class="pane4">
<div class="pane1">ONE</div>
<div class="pane2"TWO></div>
</div>
<div class="pane3">THREE</div>
<div class="clear"></div>
CSS:
body, html { height:100% }
.pane4 {
width:200px;
float:left;
height:100%;
border:1px solid #ff0000
}
.pane1 {
height:75%;
border:1px solid #00cccc
}
.pane2 {
border:1px solid #ff0000
min-height:50px;
}
.pane3 {
float:left;
width:200px;
border:1px solid #cc00cc
}
.clear { clear:both }

css difficulties with 100% height

I'm trying to create a page with a panel on the left side. The panel has a header, a content area and a footer. The main panel wrapper div is supposed to be 100% of the height of the page. The header and footer do not have a specified height because I only want them to be large enough for their text and padding while the center content area I want to be 100% of the container minus whatever the height of the header and footer is. I'm not sure how or if I can do this in css. Anyone know what to do here? Thanks.
The html page & css is here - https://gist.github.com/1641918
You can use display as table to accomplish this. By setting a height of 100% on the content 'row' and then 0% on the others. Tables try and make their rows match as closely as possible the specified heights.
http://jsfiddle.net/PZALU/
html, body { height: 100%; width: 100%; }
div#container { display: table; height: 100%; width: 100%;}
div#container > div { display: table-row; }
div#container > div > div { display: table-cell; border: 1px solid gray; }
div#header { height: 0%; }
div#content {height: 100%; background: lightgray; }
div#footer { height: 0%; }
I have dealt with this on several occasions. It is possible to to with just CSS in one or two specific cases from my experience. Otherwise, you would need to tag team it with Javascript and CSS. Because, in order to set an element to 100% height, its parent element's height must be delared. Depending on how deeply nested the element is and what siblings it may or may not have before it, will determine if its possible to do with CSS alone.
One method of getting a conent container div to be 100% of the height browser's viewport is via the following styles.
html {
height:100%;
}
body {
height:100%;
}
#container {
min-height:100%;
max-height:100%;
}
<html>
<body>
<div id="container">
...
</div>
</body>
</html>
It can easily get tricky depending on the layout.

Resources