Vertical div expansion w/o fixed heights - html

Before you roll your eyes and move on, I know how to solve this problem by using a fixed height and absolution positioning with top: and bottom:, but I want to solve it without using fixed heights. I want to learn more about CSS so I'm trying to solve this a different way.
I have set up a typical navbar running across the top, and then a scrolling content div below.
However! How do I fit the bottom scrolling div container to the remaining space without using absolute coordinates? I can't do position: absolute, because then I'd need to know the height of the navbar to set "top:". And I can't do "bottom: 0" because I'd have to specify a height.
Here's the JS filddle:
http://jsfiddle.net/8dugffz4/1/
The class of interest is ".result". I currently have the height fixed, which I don't want.
Thanks, y'all.
PT
CSS:
* {
font-family: Helvetica, Sans;
border: 0px;
margin: 0px;
padding: 0px;
}
.navBar {
width: auto;
overflow: auto;
border-bottom: 1px solid #bbb;
}
.pageBar {
float: right;
}
.pager {
cursor: pointer;
float: left;
border: 1px solid #bbb;
width: 2em;
height: 2em;
line-height: 2em;
text-align: center;
margin: 5px;
margin-left: 0px;
background: #eee;
color: #bbb;
}
.pager:hover {
background: #777;
border: 1px solid black;
color: white;
}
.fliph {
-ms-transform:scale(-1,1); /* IE 9 */
-moz-transform:scale(-1,1); /* Firefox */
-webkit-transform:scale(-1,1); /* Safari and Chrome */
-o-transform:scale(-1,1); /* Opera */
}
.results {
background: gray;
width: 100%;
height: 200px;
overflow: scroll;
}
.line {
height: 10em;
line-height: 10em;
border: 1px solid red;
}
HTML:
<body>
<div class='navBar'>
<div class='pageBar'>
<div class='pager'>◁</div>
<div class='pager'>1</div>
<div class='pager fliph'>◁</div>
</div>
</div>
<div class='results'>
<div class='line'>Line1</div>
<div class='line'>Line2</div>
<div class='line'>Line3</div>
<div class='line'>Line4</div>
</div>
</body>

Here's a solution that uses display: table and can actually achieve fluid heights:
http://jsfiddle.net/8dugffz4/8/
And a minimalistic snippet in case you want to see specifically what I did:
* {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
}
#table {
display: table;
height: 100%;
width: 100%;
}
#table > div {
display: table-row;
}
#navbar {
height: 45px;
opacity: .5;
}
#navbar > div {
height: 100%;
background: black;
}
#results {
height: 100%;
}
#results > div {
height: 100%;
overflow: auto;
background: green;
}
<div id="table">
<div id="navbar">
<div></div>
</div>
<div id="results">
<div></div>
</div>
</div>

If you're just looking for an alternative to the position: absolute method, you could use the height: 100% method:
html, body { height: 100%; }
body { box-sizing: border-box; padding-top: 45px; }
.navBar { height: 45px; margin-top: -45px; }
.results { height: 100%; }
Like so: http://jsfiddle.net/8dugffz4/7/

Related

Why does block with text shift to bottom?

Why does block with text shift to the bottom? I know how to fix this issue (need to add "overflow: hidden" to the box), but I don't understand why it shift to the bottom, text inside the box is short, margins in browser-inspector are same as margins of example without text.
Example of the problem
HTML:
<div class="with-text">
<div class="box1">
SIMPLE TEXT
</div>
<div class="box2">
</div>
</div>
<div class="without-text">
<div class="box1">
</div>
<div class="box2">
</div>
</div>
CSS:
html, body {
font-size: 10px;
margin: 0;
height: 100%;
}
.box1 {
display: inline-block;
margin: 5px;
width: 50px;
height: 50px;
background: blue;
/* Fix the problem */
/* overflow: hidden; */
color: white;
}
.box2 {
display: inline-block;
margin: 5px;
width: 50px;
height: 50px;
background: red;
}
.with-text:before {
display: block;
content: "with-text";
text-transform: uppercase;
margin: 1rem;
}
.with-text {
box-sizing: border-box;
height: 50%;
border: 1px solid;
}
.without-text:before {
display: block;
content: "without text";
text-transform: uppercase;
margin: 1rem;
}
.without-text {
box-sizing: border-box;
height: 50%;
border: 2px solid black;
}
The problem is that by default vertical alignment of inline elements – baseline,
The text inside element affects it and pushes div to the bottom.
Use vertical-align: top to solve issue.
You can try to add vertical-align:
.box1 {
display: inline-block;
margin: 5px;
width: 50px;
height: 50px;
background: blue;
/* overflow: hidden; */
color: white;
vertical-align:top;
}

stack the 2nd element first and then the 3rd element

I have three divs. I want them to be in one line so I used inline-block. When I resize the window the third element (nav) stacks and then the 2nd element (searchBar). I want the 2nd element stacks first and then the 3rd one. For undoing, the 3rd element and then the 2nd element.
body {
margin: 0px;
padding: 0px;
}
header {
width: 100%;
min-eight: 48px;
position: fixed;
background: #ffffff;
padding-bottom: 5px;
border-bottom: 2px solid #fed700;
}
nav {
width: 489.7px;
height: 18px;
background: red;
display: inline-block;
}
#searchBar {
width: 330px;
height: 16px;
background: blue;
display: inline-block;
white-space: nowrap;
}
#logo {
width: 220px;
height: 32px;
background: green;
display: inline-block;
}
<header>
<div id=logo>logo
</div>
<div id=searchBar>searchBar
</div>
<nav>nav
</nav>
</header>
You could use an inline-block wrapper with a min-width, wrapping the nav and searchBar. That would give the result you wanted in with the code sample supplied, but might cause problems in the real world, depending on your requirements.
body {
margin: 0px;
padding: 0px;
}
header {
width: 100%;
min-height: 48px;
position: fixed;
background: #ffffff;
padding-bottom: 5px;
border-bottom: 2px solid #fed700;
}
.wrapper {
min-width: 50%;
display: inline-block;
}
nav {
width: 489.7px;
height: 18px;
background: red;
display: inline-block;
}
#searchBar {
width: 330px;
height: 16px;
background: blue;
display: inline-block;
white-space: nowrap;
}
#logo {
width: 220px;
height: 32px;
background: green;
display: inline-block;
}
<header>
<div id=logo>logo
</div>
<div class="wrapper">
<div id=searchBar>searchBar
</div>
<nav>nav
</nav>
</div>
</header>

How can I get these divs to expand to full width inside an scrolling div?

I am trying to make a file hierarchy in html/css and I can't get these labels or the divs they are in to expand to full width. They only expand to the width of the visible area but I want the width of what they are in. Here is the fiddle to see what I am talking about. The grey area needs to all line up on the right.
a = 3;
html,
body {
height: 100%;
width: 100%;
padding: 0;
margin: 0;
}
div.hierarchy {
position: relative;
overflow: auto;
border-right: 1px solid grey;
width: 150px;
left: 0;
top: 0;
bottom: 0;
height: 100%;
}
div.hierarchy label {
display: block;
min-width: 100%;
background: #eee;
white-space: nowrap;
}
div.directory {
padding-left: 20px;
width: 100%;
}
div.directory label {
border: 1px solid grey;
width: 100%;
cursor: pointer;
}
<div class="hierarchy">
<label>Hierarchy</label>
<div class="directory">
<label>src</label>
<div class="directory">
<div class="file"><label>test.txt</label></div>
<div class="file"><label>readme.txt</label></div>
<div class="file"><label>a really long filename.txt</label></div>
</div>
</div>
</div>
You need to change your div.directory CSS class as follows:
div.directory {
display:inline-block;
padding-left: 20px;
}
I made the following changes:
1) Added display:inline-block;
2) Removed the width:100%; rule.
Here is an example:
http://jsfiddle.net/nnd7jyj1/
(As a side note, it's generally bad practice in CSS to apply both a width and either a padding or margin rule to the same element. The reason for this is that some browsers interpret the width to include the padding/margin and some don't, which leads to inconsistent results)
Simply add display:inline-block; to div.directory
html,
body {
height: 100%;
width: 100%;
padding: 0;
margin: 0;
}
div.hierarchy {
position: relative;
overflow: auto;
border-right: 1px solid grey;
width: 150px;
left: 0;
top: 0;
bottom: 0;
height: 100%;
}
div.hierarchy label {
display: block;
min-width: 100%;
background: #eee;
white-space: nowrap;
}
div.directory {
padding-left: 20px;
/* width: 100%; */
/* added */
display: inline-block;
}
div.directory label {
border: 1px solid grey;
width: 100%;
cursor: pointer;
}
<div class="hierarchy">
<label>Hierarchy</label>
<div class="directory">
<label>src</label>
<div class="directory">
<div class="file">
<label>test.txt</label>
</div>
<div class="file">
<label>readme.txt</label>
</div>
<div class="file">
<label>a really long filename.txt</label>
</div>
</div>
</div>
</div>

CSS, two columns - left with dynamic width (input), right with fixed (button)

can somebody please point me to a solution for this?
HTML
<div class="container">
<input type="text" class="left" />
<button class="right">Some button</button>
</div>
CSS
.container {
display: table;
width: 100%;
background-color: red;
}
.left, .right {
display: table-cell;
}
.right { width: 100px; }
Here is code pen sample: http://codepen.io/be-codified/pen/qdRRBY
Input field should be stretchable, button should be fixed positioned on right.
Thank you in advance.
// edit
I can not use table tag because layout needs to be responsive.
I gave the input a width of calc(100% - 110px) and the button a float:right which resulted in the following. Is that what you need? The input type you want to use is, as far as I know, not stretchable by the user.
CSS
.container {
display: table;
width: 100%;
background-color: red;
}
.left, .right {
display: table-cell;
}
.right {
width: 100px;
float: right;
}
input.left {
width: calc(100% - 110px); //This makes sure the input area is as wide as possible, while also leaving space for the button. Play with the exact measurements to get what you need.
}
I suggest you to put the form elements into <div>, so don't change their default display properties, and then set the left input box to 100% width as needed.
.container {
display: table;
width: 100%;
background-color: red;
}
.left, .right {
display: table-cell;
}
.right {
width: 100px;
}
.left input {
width: 100%;
box-sizing: border-box;
}
<div class="container">
<div class="left"><input type="text" /></div>
<div class="right"><button>Some button</button></div>
</div>
In fact, both left and right can have dynamic width, so right column always get the minimum width based on the button length.
.container {
display: table;
width: 100%;
background-color: red;
}
.left, .right {
display: table-cell;
white-space: nowrap;
}
.left {
width: 100%;
}
.left input {
width: 100%;
box-sizing: border-box;
}
<div class="container">
<div class="left"><input type="text" /></div>
<div class="right"><button>Some button</button></div>
</div>
Here is full responsive solution.
HTML
<div class="container">
<div class="input-flied-box">
<form>
<input type="text" required="required" placeholder="Right Some thing" />
<button type="submit" class="submit-button">Send</button>
</form>
</div>
</div>
CSS
/* RESPONSIVE CSS */
.container{
width: 100%;
}
.input-flied-box{
width: 100%;
}
.input-flied-box input{
padding: 6px 12px 6px 12px;
}
.submit-button{
top: inherit;
right: inherit;
position: relative;
margin-bottom: 15px;
}
#media (min-width: 768px){
.container{
width: 750px;
}
.input-flied-box{
width: 600px;
}
.input-flied-box input{
padding: 6px 101px 6px 12px;
}
.submit-button{
top: 14px;
right: 14px;
position: absolute;
margin-bottom: 0;
}
}
#media (min-width: 992px){
.container{
width: 960px;
}
}
#media (min-width: 1200px){
.container{
width: 1170px;
}
}
/* RESPONSIVE CSS END */
*:after,
*:before{
box-sizing: border-box;
}
*{
box-sizing: border-box;
}
.container:after,
.container:before{
display: table;
content: " ";
clear: both;
}
.container{
margin-left: auto;
margin-right: auto;
}
.input-flied-box {
background-color: #666666;
margin-left: auto;
margin-right: auto;
padding-left: 15px;
padding-right: 15px;
position: relative;
}
.input-flied-box input {
background-color: #ffffff;
border: 1px solid #cccccc;
height: 40px;
margin-bottom: 15px;
margin-top: 15px;
width: 100%;
border-radius: 4px;
}
.submit-button {
background-color: #fc3850;
border: medium none;
border-radius: 4px;
color: #ffffff;
font-family: Arial;
line-height: 1;
padding: 13px 30px;
text-transform: uppercase;
}
https://jsfiddle.net/bL3wgrv9/

Image disrupts div positions

I have three divs in a row, all with display: inline-block. The left one (green) contains an image. Because of that image, two other divs (blue and yellow) and the div below them (grey) are all positioned lower by height of the image.
Why does an image in one div affect positions of other divs in an inline-block row? How can I avoid it?
* {
margin: 0;
padding: 0;
border: 0;
}
body {
background: black;
}
div {
display: inline-block;
width: 300px;
height: 70px;
}
div.wrapper {
width: 900px;
height: 100px;
margin: 0 auto;
background: red;
display: block;
font-size: 0;
}
div.div1 {
background: green;
}
div.div2 {
background: blue;
}
div.div3 {
background: yellow;
}
div.div4 {
display: block;
width: 900px;
height: 30px;
background: grey;
}
<body>
<div class="wrapper">
<div class="div1">
<img src="" width="25px" height="25px">
</div>
<div class="div2">b</div>
<div class="div3">c</div>
<div class="div4">d</div>
</div>
</body>
Try float:left; display:block; instead of inline-block for div's: Demo
CSS:
.div1, .div2,.div3 {
display: block;
float:left;
width: 300px;
height: 70px;
}
There already is discussons about inline-block-elementes still have weird heights (like here): Why does inline-block cause this div to have height?
Honestly, instead of solving those, i would adress this issue with floats:
* {
margin: 0;
padding: 0;
border: 0;
}
body {
background: black;
}
div {
/*display: inline-block;*/ /* Not necessary when using floats! */
width: 300px;
height: 70px;
}
div.wrapper {
width: 900px;
height: 100px;
margin: 0 auto;
background: red;
display: block;
font-size: 0;
}
div.div1 {
background: green;
float: left; /* Added float left here */
}
div.div2 {
background: blue;
float: left; /* Added float left here */
}
div.div3 {
background: yellow;
float: left; /* Added float left here */
}
div.div4 {
display: block;
width: 900px;
height: 30px;
background: grey;
}