Column flexbox fitting within another column flexbox - css

I'm trying to get a UI that looks somewhat like this:
In the image pretend the top bar with "New York..." and the "Book it" button are fixed and the stuff between is scrollable.
The HTML I have so far is this (note that the .button and .form are just divs to try to keep the example as simple as possible)
<div class="wrapper">
<div class="sidebar"> <!-- Hidden from UI unless you swipe left to right --> </div>
<div class="inner-wrapper">
<div class="header">Title here</div>
<div class="balance-bar">$0</div>
<div class="app-content">
<div class="body-content">
<div class="form">
<input type="text"><br><br>
<input type="text"><br><br>
<input type="text"><br><br>
<input type="text"><br><br>
<input type="text"><br><br>
<input type="text"><br><br>
<input type="text"><br><br>
<input type="text"><br><br>
<input type="text"><br><br>
</div>
<div class="button">Submit</div>
</div>
</div>
</div>
</div>
The CSS is:
.button, input {
width:100%;
box-sizing: border-box;
}
.wrapper {
border: 2px solid blue;
height:200px;
overflow: auto;
}
.header {
background: lightblue;
flex-shrink: 0;
}
.balance-bar {
background: lightgreen;
flex-shrink: 0;
}
.inner-wrapper {
border: 2px solid red;
display: flex;
flex-direction: column;
}
.app-content {
border: 2px solid green;
overflow:auto;
}
.body-content {
border: 2px solid orange;
display: flex;
flex-direction:column;
}
.form {
}
.button {
background: pink;
flex-shrink: 0;
}
If I move the button outside the form and as a child of the first flexbox (so .button would be a sibling of .app-content) this all works great and you don't even need a flexbox within a flexbox. One flexbox works perfect. The issue tho is that the semantics are all wrong, you don't get built in browser features like enter to submit, and the flow for the JS to get it to work is super janky.
I was hoping with flexbox I can set the wrapper to the height of the window and flexbox would just calculate all children to fit within the window (which it does, but not for children set to flex)
http://jsbin.com/gumozexihi/1/edit?html,css,output

I hope this helps. I kept the button inside the form and gave it a position: fixed and a bottom: 0.
HTML:
<div class="wrapper">
<div class="inner-wrapper">
<div class="header">Header</div>
<div class="balance-bar">$0</div>
<div class="app-content">
<div class="body-content">
<div class="form">
<input type="text" />
<input type="text" />
<input type="text" />
<input type="text" />
<input type="text" />
<input type="text" />
<input type="text" />
<input type="text" />
<div class="button">Submit</div>
</div>
</div>
</div>
</div>
</div>
And the CSS:
html, body {
height: 100%;
margin: 0;
}
.wrapper {
height: 100%;
}
.inner-wrapper {
height: 100%;
display: flex;
flex-direction: column;
}
.app-content {
flex: 1;
overflow: auto;
}
.body-content {
height: 1000px;
display: flex;
flex-direction: column;
}
.button {
position: fixed;
bottom: 0;
width: 100%;
}
I added height: 1000px to .body-content to mimic having more content than the available screen height. And I fixed the button to the bottom using position: fixed and bottom: 0, which may not be ideal solutions but it seems to work while keeping the button inside the form element.
Update
Just saw you specifically didn't want to use a fixed position on the button. If I can find another solution I'll edit this response, but for a single button this should do the trick.

Related

Keep side bar full height

I am pretty bad with css, so I was wondering how I can keep my sidebar full height, even though it doesnt have full content.
This is my css:
#wrapper {
display: flex;
flex-wrap: wrap;
background-color: yellow;
}
#wrapper .sideBar {
background-color: green;
width: 200px;
margin-left: 10px;
overflow-x: hidden;
padding-top: 20px;
}
#wrapper .productsBox{
width: 250px;
margin: 3px;
}
But I get this result
However I want a result that looks like this:
Any idea how I can fix this? And I want to have a responsive view, so when a user use phone to browse it displays a decent view. Thats the reason I use the wrapper.
html:
<div id="wrapper">
<form method="get" id="sortForm">
#Html.DropDownList("sort", new SelectList(ViewBag.sortOptions,"Value","Text"), new {#class="form-control", onchange = "sortingChanged()" })
<div class="sideBar">
<strong>Search for products</strong>
<input type="text" class="searchBar" name="SearchString" value="#ViewData["CurrentFilter"]" placeholder="Search.."/>
<hr />
<h6>Price</h6>
<div>
<input type="number" class="priceRangeInput" name="minPrice" value="#ViewData["MinPriceFilter"]" oninput="validity.valid||(value='');" />
<span>Min</span>
</div>
<div>
<input type="number" class="priceRangeInput" name="maxPrice" value="#ViewData["MaxPriceFilter"]" oninput="validity.valid||(value='');" />
<span>Max</span>
</div>
<br />
<hr>
<h6>Types</h6>
<button type="submit" class="btn customGreen" >Set filters</button>
</form>
<br />
</div>
#{
foreach(var p in #Model)
{
<div class="productsBox">
<div class="card">
<a asp-action="Details" asp-route-id="#p.Id">
<img alt="#p.Name" class="contain" src="#p.FilePath" height="300" style="width: 100%;" />
</a>
<h3>#p.Name</h3>
<p class="price">#p.Price kr/#p.Unit</p>
<a asp-action="Details" asp-route-id="#p.Id">
<button class="customGreen">See more</button>
</a>
</div>
</div>
}
}
</div>
html, body {
height: 100%
}
html,
body {
height: 100%; /* to set height to 100% */
}
body {
margin: 0; /* to remove default margins */
}
#wrapper {
height: 100%; /* to set height to 100% */
}
#wrapper {
display: flex;
background-color: yellow;
}
.sideBar {
background-color: #000;
width: 200px;
color: #fff;
overflow-x: hidden;
padding-top: 20px;
}
.product-wrapper {
width: calc(100% - 200px); /* 100% - (sidebar width) */
}
.productsBox {
display: inline-block;
width: 150px;
height: 150px;
color: #fff;
margin: 3px;
background: #2f910f;
}
<html>
<body>
<div id="wrapper">
<div class="sideBar">
Sidebar
</div>
<div class="product-wrapper">
<div class="productsBox">
Item
</div>
</div>
</div>
</body>
</html>
You should take .sideBar out of the #wrapper container and apply width: calc(100% - 210px) to #wrapper (i.e. the width of the container/window minus sidebar minus its left margin). That way both together will be 100% wide, but the contents of #wrapper will not go under the sidebar.
you should add side bar and another containts in different divs and add this code to it:
.wrapper{
display:flex;
flex-direction:row;
}
.sidebar{
background-color:red;
width:50%;
}
.containts{
width:50%;
background-color:green;
}
<div class="wrapper">
<div class="sidebar">
sidebar
</div>
<div class="containts">
containts
</div>
</div>
Add the following code in css it worked for me
height: 100%;

How to position two block items on a single line

I'm trying aligned on one line sections new-setstion, user-section with inline-block but when I put text they diverge.
This is my css code, if you have better suggestions or criticisms please share them.
.page-content {
margin: 0 auto;
text-align: center;
}
div.news-section {
display: inline-block;
max-width: 500px;
min-width: 200px;
background-color: #fff;
word-wrap: break-word;
text-align: left;
}
div.user-section {
display: inline-block;
max-width: 300px;
min-width: 200px;
background-color: #fff;
word-wrap: break-word;
text-align: left;
}
This is my html code
<div class="page-content">
<div class="news-section">
<div class="news-section-header">
<h2>News</h2>
</div>
<!-- content -->
</div>
<div class="user-section">
<div class="user-section-header">
<h2>User section</h2>
</div>
<form class="user-login-form" method="POST">
<div><input type="email" name="user-name" placeholder="John-Doe#mail.com" /></div>
<div><input type="password" name="user-pass" placeholder="*****" /></div>
<div><input type="submit" name="sub-button" value="Login"/></div>
</form>
<!-- another div content -->
</div>
I think you want something like this: https://jsfiddle.net/oqvzraxs/, if I understood correctly your question.
I have added display: inline-flex to .page-content
.page-content {
display: inline-flex;
margin: 0 auto;
text-align: center;
}

Flexbox 2x2 grid - input inside overflows the flex container

I want to have a flexbox 2x2 grid that contain a random number of elements (odd or even). I've achieved to create this flexbox without any problems.
When I added my content: input fields with width 100% I noticed that those are bigger then their flex container which seems odd. In the example this is easy to spot on the last red box.
How can I make the input fields be 100% of the flex container?
.flex-grid {
display: flex;
flex-wrap: wrap;
height: 500px;
}
.grid-item {
flex: 1 1 50%;
background: #F90;
border-top: solid 1px #000;
}
.grid-item:nth-child(odd) {
background: #F00;
flex: 0 0 50%;
}
input {
width: 100%;
}
<div class="flex-grid">
<div class="grid-item">
<input type="text" value="email">
</div>
<div class="grid-item">
<input type="text" value="email">
</div>
<div class="grid-item">
<input type="text" value="email">
</div>
</div>
Fiddle: https://jsfiddle.net/x3pyenkL/
From Documentation:
The box-sizing property is used to alter the default CSS box model used to calculate width and height of the elements.
Set box-sizing: border-box for <input> elements.
input {
box-sizing: border-box;
width: 100%;
}
Or better to add for all elements of your page for consistency.
* {
box-sizing: border-box;
}
.flex-grid {
display: flex;
flex-wrap: wrap;
height: 500px;
}
.grid-item {
flex: 1 1 50%;
background: #F90;
border-top: solid 1px #000;
}
.grid-item:nth-child(odd) {
background: #F00;
flex: 0 0 50%;
}
input {
box-sizing: border-box;
width: 100%;
}
<div class="flex-grid">
<div class="grid-item">
<input type="text" value="email">
</div>
<div class="grid-item">
<input type="text" value="email">
</div>
<div class="grid-item">
<input type="text" value="email">
</div>
</div>

div shifts to the bottom of the page with any content

I am attempting to put together a web page that has four areas: a header, footer, content, and controls. The header and footer should be fixed at the top and bottom of the page (respectively) and automatically size to their content. The controls should go on the far right side of the page (vertically between the header and footer) and is fixed-width. The content area should fill the remainder of the page.
I had this working, but now whenever I add any kind of content (even just a single-word paragraph element), the controls area moves to almost the very bottom of the page. You can see what I'm referring to here: http://jsfiddle.net/ym8vY/1/
If I leave the controls div completely empty, it lays out exactly how I want it: http://jsfiddle.net/ym8vY/
My body currently looks like:
<header>
<p>Header</p>
</header>
<div class="main">
<div id="streamGraph" class="page">
<div class="page-row">
<div class="page-content-container-outer">
<div class="page-content-container-inner">
<div id="graphContainer" class="page-content"></div>
</div>
</div>
<div class="page-controls-container-outer">
<div class="page-controls-container-inner">
<div class="page-controls"><!-- If anything goes inside here, it breaks -->
<div style="display: table; height: 100%;">
<div style="display: table-row; height: 0;">
<div>
<label for="sampleCount"># Samples:</label>
<input type="text" id="sampleCount" name="sampleCount" value="100" />
</div>
<div>
<label for="tagCount"># Tags:</label>
<input type="text" id="tagCount" name="tagCount" value="25" />
</div>
<div>
<label for="fromDate">From:</label>
<input type="date" id="fromDate" name="fromDate" />
</div>
<div>
<label for="toDate">To:</label>
<input type="date" id="toDate" name="toDate" />
</div>
<button id="tagsButton">Customize Tags</button>
<button id="refreshButton">Apply</button>
</div>
<div style="display: table-row;">
<div id="tagContainer" style="overflow: auto; height: 100%;"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<footer>
<p>Footer</p>
</footer>
And my CSS is:
html, body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
body {
display: table;
}
header, .main, footer {
display: table-row;
width: 100%;
}
header, footer {
background: lightgray;
}
.main {
height: 100%;
}
.page {
height: 100%;
display: table;
}
.page-row {
display: table-row;
width: 100%;
}
.page-content-container-outer {
display: table-cell;
width: 100%;
height: 100%;
padding: 10px;
}
.page-controls-container-outer {
display: table-cell;
height: 100%;
padding: 10px;
}
.page-content-container-inner {
border: solid;
border-color: gainsboro;
border-width: 5px;
border-radius: 10px;
width: 100%;
height: 100%;
padding: 5px;
}
.page-controls-container-inner {
border: solid;
border-color: gainsboro;
border-width: 5px;
border-radius: 10px;
height: 100%;
padding: 5px;
}
.page-controls {
height: 100%;
width: 300px;
}
.page-content {
height: 100%;
}
Your right-side div is being pushed down to the baseline. Add vertical-align:top to fix it:
div
{
vertical-align: top;
}
JSFiddle
Side note: The default value for vertical-align is baseline. Always keep this in mind when using cells and inline-blocks.
Add vertical-align:top; to your .page-controls-container-outer class
Change this
<div style="display: table-row; height: 0;">
to this
<div style="display: table-row; height: 0; float:left;">

CSS: Getting 2 children DIVs on same line

Am using Ninja Forms on a WP website. There are 2 different fields (textbox & submit button) that are separate DIVs, both children of single DIV.
They appear on consecutive lines and I cannot seem to get the on same line. Help?
Can see current code of the DIVs on the site: http://theroadmap.co/generation/
<div id="ninja_forms_form_2_all_fields_wrap" class="ninja-forms-all-fields-wrap">
<div class="field-wrap text-wrap label-above ninjacomment-wrap" id="ninja_forms_field_9_div_wrap" data-visible="1">
<input type="hidden" id="ninja_forms_field_9_type" value="text">
<label for="ninja_forms_field_9" id="ninja_forms_field_9_label" class=""> </label>
<input id="ninja_forms_field_9" data-mask="" name="ninja_forms_field_9" type="text" class="ninja-forms-field ninjacomment " value="" rel="9">
<div id="ninja_forms_field_9_error" style="display:none;" class="ninja-forms-field-error">
</div>
</div>
<div class="field-wrap submit-wrap label-left ninjasubmit-wrap" id="ninja_forms_field_10_div_wrap" data-visible="1">
<input type="hidden" id="ninja_forms_field_10_type" value="submit">
<input type="submit" name="_ninja_forms_field_10" class="ninja-forms-field ninjasubmit" id="ninja_forms_field_10" value="Suggest a link!" rel="10">
<div id="ninja_forms_field_10_error" style="display:none;" class="ninja-forms-field-error">
</div>
</div>
</div>
Modifications I've added so far:
/* Ninja Form mods */
.ninjacomment {
background: #ffbf00 !important;
border: 3px;
color: black !important;
width: 50%;
}
#ninja_forms_field_9 {
margin-left: 0;
width: 30%;
float: left;
position: inline-block;
}
#ninja_forms_field_10 {
margin-left: 0;
float: right;
position: inline-block;
}
.ninja-forms-all-fields-wrap {
overflow: hidden;
}
Thanks!
You can get elements on the same line several ways.
Sample markup:
<div class="parent">
<div class="child"></div>
<div class="child"></div>
</div>
inline-block
.child {
display: inline-block;
width: 40%; /* adjust */
}
Floats
.child {
float: left; /* or right */
width: 40%; /*adjust */
}
display: table
.parent {
display: table;
width: 100%;
}
.child {
display: table-cell;
width: 40%; /* adjust */
}
white-space: nowrap
.parent {
white-space: nowrap /* children will stay on the same line no matter how wide */
}
<div id="wrapper">
<div id="left">
<input id="ninja_forms_field_9" data-mask="" name="ninja_forms_field_9" type="text" class="ninja-forms-field ninjacomment " value="" rel="9"></input>
</div>
<div id="right">
<input type="submit" name="_ninja_forms_field_10" class="ninja-forms-field ninjasubmit" id="ninja_forms_field_10" value="Suggest a link!" rel="10"></input>
</div>
CSS
#wrapper {
width:300px;
}
#left {
float:left;
width:146px;
}
#right {
float:right;
width:148px;
}
Working Fiddle

Resources