Proportionately increasing columns width - javascript

let's say I have number of columns of different width e.g.:
| 100 | 200 | 55 | 450 | empty space
And now I need to adjust the width of every column the way that the entire row fits in its container, and takes 100%.
I could of course set .row { max-width: 100% } and set the widest column to 100%, but I want to make it the way so every column takes available space proportionally. Any ideas?

You can use both display: table and display: table-cell.
As an example:
* {
box-sizing: border-box;
}
html, body {
width: 100%;
}
div {
width: 100%;
min-width: 100;
display: table;
}
div > div {
min-width: auto;
width: auto;
display: table-cell;
border-right: 1px solid #000;
text-align: center;
}
div > div:first-of-type {
border-left: 1px solid #000;
}
<div>
<div>ABCDE</div>
<div>FG</div>
<div>HIJKLM</div>
<div>N</div>
<div>OPQ</div>
<div>RSTUVWX</div>
<div>YZ</div>
</div>
Demo

You can also use percentages in your widths defining. (If you know the proportion of every element.)
div {
float: left;
}
#container {
width: 100%;
}
#e1 {
width: 30%;
}
#e2 {
width: 50%;
}
#e3 {
width: 20%;
}
<div id="container">
<div id="e1">XX</div>
<div id="e2">XX</div>
<div id="e3">XX</div>
</div>
Make sure your box-sizing is set correctly in CSS (box-sizing: border-box;), otherwise paddings and borders will overflow the width. :)

Related

Is there a way to resize grid boxes?

I have a react app where I'm creating about a million grid boxes, all the boxes ought to fit into the immediate screen (I want each box to be tiny asf). I'm using js to calculate each box's height and width in relation to the number of boxes.
var numOfBoxes = 1000 // this number can change anytime
var [height, width] = `${100/numberOfBoxes}%`
I created the grid using a CSS I found on StackOverflow
#root {
width: 100vw;
height: 100vh
}
// I tried to use vh and vw to make the #root element fit the initial screen
.square-container {
display: flex;
height: 100%;
width: 100%;
flex-wrap: wrap;
}
.square {
position: relative;
flex-basis: calc(25% - 10px);
margin: 5px;
border: 1px solid;
box-sizing: border-box;
}
.square::before {
content: '';
display: block;
padding-top: 100%;
}
.square .content {
position: absolute;
top: 0; left: 0;
height: 100%;
width: 100%;
}
But the squares remain the same size when I try to increase or decrease numOfBoxes. I tried changing the height and width from the DevTools but to no avail.
It looks like this if I render 100 boxes or 1000
Can someone point me in the right direction?
You can add a CSS variable to the root element, use it as part of the grid class, and then update it with setProperty.
// Using a setTimeout for this demo, but you would
// be adding this to your render method I expect
function changeWidth(width, count = 1) {
document.documentElement.style.setProperty('--square-width', `${width}px`);
if (count < 5) setTimeout(changeWidth, 2000, width +=5, ++count)
}
changeWidth(5);
:root {
--square-width: 10px
}
.container {
display: grid;
grid-template-columns: repeat(3, var(--square-width));
grid-gap: 5px;
}
.container div {
background-color: red;
aspect-ratio: 1;
}
<div class="container">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>

Increase the height of all elements when one element increases (equal height columns)

I want all 100% height elements to expand when the size of the body expands.
In the example pressing the button will add a red div - the two columns adjacent should stretch to account for this. In the end all columns should reach the bottom completely, one with blue then red, the other two just blue.
I'm looking into flex, and it doesn't seem like this would work, but any suggestions are appreciated.
In any case best solution is CSS, but if this is impossible pure JS is also fine.
span = document.getElementsByTagName("span")[0];
function addelem() {
span.appendChild(document.createElement('div'));
};
html, body{
height: 100%;
}
span {
display: inline-block;
background-color: blue;
width: 30px;
height: 100%;
vertical-align: top;
}
div {
background-color: red;
width: 30px;
height: 30px;
}
<span><span></span></span>
<span></span>
<span><button onclick="return addelem()">+</button></span>
This is what I expect the frame to look like at the bottom after button is pressed and scrolled down:
EDIT
I changed the snippet so the button appends the div to an existing child and causes overflow, as per the comments below suggest.
An initial setting of a flex container is align-items: stretch. This means that flex items will expand to cover the full length of the container along the cross axis.
In a container with flex-direction: row, the cross axis is vertical, so items will expand to full height.
In your demo code, the divs (red) are being added as children of a span column (blue). These divs are being added to the end, forcing the column to grow.
In a row-direction flex container, with no heights specified that would override align-items: stretch, the other columns will follow suit.
span = document.getElementsByTagName("span")[0];
function addelem() {
span.appendChild(document.createElement('div'));
};
body {
display: flex;
min-height: 100vh;
}
body > span {
width: 30px;
margin-right: 5px;
background-color: blue;
display: flex;
flex-direction: column;
}
body > span:first-child span {
flex: 0 0 100vh;
}
div {
background-color: red;
width: 30px;
height: 30px;
}
button {
margin-bottom: auto;
}
<span><span></span></span>
<span></span>
<span><button onclick="return addelem()">+</button></span>
You should use Flexbox twice, once in the outer container, and once in the container containing the appended child elements.
Here is your modified code:
span = document.getElementsByTagName("span")[0];
function addelem() {
span.appendChild(document.createElement('div'));
};
html, body{
height: 100%;
/* new */
display: flex;
}
/* new */
body > span{margin-right: 4px;}
span {
/*display: inline-block;*/
background-color: blue;
width: 30px;
height: 100%;
vertical-align: top;
/* new */
display: flex;
flex-flow: column;
align-items: flex-end;
}
div {
background-color: red;
width: 30px;
height: 30px;
/* new */
flex: 1 0 auto;
}
<span><span></span></span>
<span></span>
<span><button onclick="return addelem()">+</button></span>

A circle element next to a fluid rounded element

Is the following layout possible with CSS? If not, is there a better solution than my current JS solution? See the fiddle for a complete example.
+--------------------+
| |
| |
| |
| |
| |
| |
| |
| |
| |
|--------------------+
|+----+ +----------+| container height in percentage, e.g. 20% of window
|| 1 | | 2 || button 1: a circle based on container height
|+----+ +----------+| button 2: fill available space and fully round corners
+--------------------+
The basic issue is that the first element needs to be a circle, i.e. a rounded square, based on the height of the container. And the second element should fill the rest of the space with the same border-radius.
Following is how I solved it with JS, but it does not seem to be too reliable on mobile devices. And the project is basically mobile-only. Also, if the layout is too dependent on JS, it will cause other trouble when doing fancy transitions etc. with CSS.
Fiddle: http://jsfiddle.net/n52x1ws1/3/
$(document).ready(function(){
var height = $(".device-fluid").find(".btn-circle").height();
var borderRadius = height / 2;
$(".device-fluid").find(".btn-circle").css("width", height);
$(".device-fluid").find(".btn-circle").css("border-radius", borderRadius);
var fluidWidth = $(".device-fluid").find(".container").width() - height - 15;
$(".device-fluid").find(".btn-fluid").css("width", fluidWidth);
$(".device-fluid").find(".btn-fluid").css("border-radius", borderRadius);
});
* {
box-sizing: border-box;
font-family: sans-serif;
}
.device {
display: inline-block;
position: relative;
width: 320px;
height: 480px;
border: 2px solid #ccc;
margin: 30px;
text-align: center;
}
.label {
margin-top: 30px;
}
.container {
position: absolute;
bottom: 0;
width: 100%;
height: 20%;
padding: 15px;
background: #f7f7f7;
}
.btn {
height: 100%;
}
.btn-circle {
float: left;
}
.btn-fluid {
float: right;
}
.device-fixed .btn-circle {
width: 66px; /* easy since we know the height */
border-radius: 33px;
background: #2ecc71;
}
.device-fixed .btn-fluid {
width: 205px; /* available space minus a 15px margin */
border-radius: 33px;
background: #27ae60;
}
.device-fluid .btn-circle {
width: 20%; /* this needs to be equal to the height */
border-radius: 50%;
background: #2ecc71;
}
.device-fluid .btn-fluid {
width: 75%; /* this needs to fill the rest of the available space minus a 15px margin */
border-radius: 50%;
background: #27ae60;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div class="device device-fixed">
<div class="label">fixed</div>
<div class="container">
<div class="btn btn-circle"></div>
<div class="btn btn-fluid"></div>
</div>
</div>
<div class="device device-fluid">
<div class="label">fluid with JS</div>
<div class="container">
<div class="btn btn-circle"></div>
<div class="btn btn-fluid"></div>
</div>
</div>
I'm not exactly sure what you mean by
container height in percentage, e.g. 20% of window
If that means that the height of the container is determined by the size of the viewport you can use the viewport units. 1vh equals 1% of the viewport height.
.container {
height: 20vh;
}
You can then easily make a circle based on this height:
.btn-circle{
height: 20vh;
width: 20vh;
border-radius: 10vh;
}
The next div should fill the available space
.btn-fluid{
height: 20vh;
width: calc(100vw - 20vh); /*100% of the viewport width minus the space for the square*/
border-radius: 10vh;
}
It looks like this in a fiddle.

How to make div take all the height available?

I have this HTML:
<div>
<span></span>
<textarea></textarea>
</div>
The Span can take up one or more lines (depends on the text it has and size of the Div). I want the Textarea to take all of the height left in div.
Please no jQuery.
https://jsfiddle.net/ntme8Lt4/
The CSS/style tag for that would just be max-height:100%; and width:100%;
This would hold the div's size constant if it is set to a percentage of its parent container or a constant value like 900px.
Since the size of span is not known, just leave it unspecified so it auto-sizes to content.
There's a circular issue here - the height of the div is (normally) determined by the size of its components. You need something to break the circle and determine the height of either the div or the text area.
You can use offsetHeight to get the heights of the different elements, and from there it is just a calculation of the container - span element to find the remaining.
document.querySelector('textarea').style.height = (document.querySelector('div').offsetHeight-document.querySelector('span').offsetHeight)+'px'
http://jsfiddle.net/rhbritton/4eck8dua/1/
If you're just wanting to use pure CSS and without the needs of tables etc you could try this approach.
HTML:
<div>
<span>
Hello<br>
Hello<br>
Hello
</span>
<textarea></textarea>
</div>
CSS:
div {
width: 400px;
height: 300px;
overflow: hidden;
border: 1px solid red;
}
span {
width: 100%;
display: block;
background-color: red;
}
textarea {
width: 100%;
height: 100%;
background-color: blue;
}
JSFiddle
Let me know if this works for you.
You can use clientWidth and clientHeight if your willing to use pure JS:
Here is the fiddle
function test()
{
var div = document.getElementById("testDiv");
var span = document.getElementById("testSpan");
var textArea = document.getElementById("testTextArea");
var height = div.clientHeight - span.clientHeight;
textArea.style.height = (height - 5) + "px";
textArea.style.width = (div.clientWidth - 5) + "px";
}
test();
Reference
you can use flex
div
{
display: flex;
flex-direction: column; /*layout top to bottom*/
height: 300px;
width: 400px;
border: 1px solid red;
}
span
{
display: block;
background-color: red;
}
textarea
{
background-color: blue;
height: 100%;
width: 100%;
flex-grow: 1; /*take up remaining space in flex container*/
}
}
https://jsfiddle.net/ntme8Lt4/13/
Thanks to the "possible duplicate" I came up with this solution:
<div>
<span>Hello<br>World</span>
<b><textarea></textarea></b>
</div>
div
{
height: 300px;
width: 400px;
border: 1px solid red;
display: table;
}
span
{
display: block;
background-color: red;
}
b
{
height: 100%;
width: 100%;
display: table-row;
}
textarea
{
height: 100%;
width: 100%;
background-color: blue;
}
https://jsfiddle.net/c42go079/

Emulating a fixed sidebar template issues

am trying to emulate this theme:
http://themetrust.com/demos/ink/?project=the-city-of-samba
But instead make the blog post always remain centered in the right hand side (space outside of the fixed sidebar) and have the blog post be of a % width.
I currently have this set up on my site, but am using a percentage based sidebar which looks awful.
Here is a JSfiddle recreating in basic terms the theme from above:
http://jsfiddle.net/Uyv6w/4/
All i am after is to make that grey inner div always remain centered inside the red content div.
Incase JSFiddle goes down and for future ref:
HTML:
<div id="container">
<div id="sidebar"></div>
<div id="content">
<div id="inner"></div>
</div
</div>
CSS:
* {
margin: 0; padding: 0;
}
html, body {
width: 100%;
height: 100%;
background-color: #333;
}
#container {
height: 100%;
width: 100%;
}
#sidebar {
height: 100%;
width: 100px;
background-color: #9b59b6;
position: fixed;
}
#content {
width: 100%;
background-color: #f00;
}
#inner {
width: 60%;
margin-left: 150px;
background-color: #888;
height: 1000px;
}
Thanks.
There are just 2 properties to change in ordre to make this work the way you want :
#content {
/* width: 100%; */
margin-left: 100px; /* the width of you sidebar.
Since #content is a div, a block-level element
, its width will be automatically 100%
, minus the margins */
background-color: #f00;
}
#inner {
width: 60%;
/* margin-left: 150px; */
margin-left: auto;
margin-right: auto; /* having margin-left & right set to auto will center your div.
you could also use "margin: 0 auto" */
background-color: #888;
height: 1000px;
}
I have updated you JSFiddle example here : http://jsfiddle.net/Uyv6w/5/
http://jsbin.com/requv/1/edit
if you set body, html (and the container) to height 100%, it will not be able to to scroll.
the height should be more then 100%.

Categories

Resources