Div's width adjusting if another div is hidden or not? - html

In my body i want two divs with content side by side that each has a width of 50% of the screen. But i want to be able to hide/show the first div and then the second divs width responds to this changing it's width to 100% or 50%. Filling the body or the rest of the body depending on if the first div is hidden.
Any ideas how to do this? (I know how to show/hide with jquery, im thinking of the HTML)

Use floating only to the first element, and let the second one fit the remaining space.
Then, if the element is visible with width:50%, the second one will fill the other half. But if the first one is hidden, the second one will fill whole screen.
Demo
HTML:
<input type="button" id="btn" value="toggle" />
<div id="wrapper">
<div id="left">Foo</div>
<div id="right">Bar</div>
</div>
CSS:
#wrapper, #right {
overflow: hidden;
}
#left {
float: left;
width: 50%;
background-color: #ffa;
}
#right {
background-color: #faf;
}
.hide {
display: none;
}
JS:
var left = document.getElementById('left');
document.getElementById('btn').onclick = function() {
left.className = left.className ? '' : 'hide';
};

Another possibility: use display: table-cell. This has the advantage over floats that both columns will have same height, and setting wrapper's height will also set it for both columns.
Demo
HTML:
<input type="button" id="btn" value="toggle" />
<div id="wrapper">
<div id="left">Foo</div>
<div id="right">Bar</div>
</div>
CSS:
#wrapper {
display: table;
width: 100%;
}
#left, #right {
display: table-cell;
}
#left {
background-color: #ffa;
}
#right {
background-color: #faf;
}
.hide {
display: none !important;
}
JS:
var left = document.getElementById('left');
document.getElementById('btn').onclick = function() {
left.className = left.className ? '' : 'hide';
};

You can use flexbox and JQuery to do this with as many divs as you'd like.
https://jsfiddle.net/L8kfty5n/5/
function hideandshow() {
if ($('.hide').is(":checked"))
$("#div1").show();
else
$("#div1").hide();
}
.container {
display: flex;
flex-flow: row nowrap;
}
#div1,
#div2,
#div3 {
flex-grow: 1;
flex-basis: calc(100% / 3);
border: 1px solid #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<div class="container">
<div id="div1">This disappears</div>
<div id="div2">This grows</div>
<div id="div3">This grows too</div>
</div>
<input class="hide" type="checkbox" name="hide" value="1" onchange="hideandshow()" checked/>

Related

.container > .wrapper > img: maximize img, but not larger than .container (grandparent) - how?

I have .container > .wrapper > img. Here is a task:
img must have maximum width/height possible, keeping it's aspect ratio, being 100% visible and not exceeding the .container's size.
Image must not exceed it's natural size.
Width/height of the image are not known.
.container is known to be of a fixed (in pixels) width/height, but exact dimensions are not known.
.wrapper must tightly fit the img (must have same width and height as the image). Wrapper is a special element to put content over the image, e. g. badges. I added example labels to the snippet to demonstrate this. This should somehow be possible.
Markup:
<div class="container">
<div class="wrapper">
<div class="label">new!</div>
<img src="https://via.placeholder.com/150x300">
</div>
</div>
I thought I can use display: block; max-height: 100% for the img, but it does not work, because .wrapper (image parent) height is not fixed, and it can't be fixed - see point 5.
What else can I do to achieve described task with pure CSS? I'd prefer solution that works in IE11, but others will be also appreciated.
EDIT: It is really important that container and image can be of any size. I added settings to the snippet for tests on different sizes.
If an image is larger than container, it should render not larger than container.
If an image is smaller than container, it should render not larger than is's natural size.
It should work with horizontal container/vertical image AND vertical container/horizontal image.
EDIT 2: It is also really important that .wrapper is not just a "nasty interfering" element. It is functional: wrapper is used to place absolute positioned content over the image inside it (e.g. labels, badges), it must support transforms (mirror, translate), css filters etc, generally speaking - all the stuff we usually do with block elements.
Playground:
$(function() {
$('input[name=container-width]').on('change', function() {
$('.container').css('width', $(this).val() + 'px')
})
$('input[name=container-height]').on('change', function() {
$('.container').css('height', $(this).val() + 'px')
})
$('input[name=image-width]').on('change', function() {
var width = $(this).val()
var height = $('input[name=image-height]').val()
$('img')[0].src = 'http://via.placeholder.com/' + width + 'x' + height
})
$('input[name=image-height]').on('change', function() {
var height = $(this).val()
var width = $('input[name=image-width]').val()
$('img')[0].src = 'http://via.placeholder.com/' + width + 'x' + height
})
})
.container {
width: 200px; /* can have any value in pixels */
height: 200px; /* can have any value in pixels */
background-color: green;
}
.wrapper {
outline: 1px solid yellow;
position: relative; /* for label */
}
.label {
position: absolute;
background-color: blue;
color: white;
}
.label.-top-left {
top: 10px;
left: 10px;
}
.label.-bottom-right {
bottom: 10px;
right: 10px;
}
<h2>Settings</h2>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Container: width <input type="number" step="10" name="container-width" value="200"> height <input type="number" step="10" name="container-height" value="200">
<br>
Image: width <input type="number" step="10" name="image-width" value="150"> height <input type="number" step="10" name="image-height" value="300">
<br>
<br>
<h2>Demo</h2>
<div class="container">
<div class="wrapper">
<div class="label -top-left">new!</div>
<div class="label -bottom-right">good!</div>
<img src="http://via.placeholder.com/150x300">
</div>
</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<h2>How it should look like</h2>
<p>This is not the solution, because is has many hardcoded dimensions. It's just a visual demo of what I want to achieve.</p>
<div style="width: 200px; height: 200px;background-color: green">
<div style="width: 100px; height: 200px; position: relative;outline: 1px solid yellow">
<div style="position: absolute;
top: 10px;
left: 10px;
background-color: blue;
color: white;">new!</div>
<div style="position: absolute;
bottom: 10px;
right: 10px;
background-color: blue;
color: white;">good!</div>
<img style="max-width: 100%; max-height: 100%;" src="http://via.placeholder.com/150x300">
</div>
</div>
Does this work for you?
.container {
width: 200px;
/* can have any value in pixels */
height: 200px;
/* can have any value in pixels */
background-color: green;
}
.container-2 {
width: 300px;
height: 300px;
}
.wrapper {
outline: 1px solid yellow;
display: inline;
height: inherit;
}
img {
width: auto;
max-height: 100%;
display: inline-block;
vertical-align: bottom;
}
<div class="container">
<div class="wrapper">
<img src="http://via.placeholder.com/150x300">
</div>
</div>
<br>
<div class="container container-2">
<div class="wrapper">
<img src="http://via.placeholder.com/30">
</div>
</div>
check out below code this should work for you
you need to apply max-width: 100% and max-height:100% to your img
and display: inline; to your img parent div
.container {
width: 200px; /* can have any value in pixels */
height: 200px; /* can have any value in pixels */
background-color: green;
}
.wrapper {
outline: 1px solid yellow;
display: inline;
}
.wrapper img{
max-width: 100%;
max-height: 100%;
height: auto;
vertical-align: top;
}
<div class="container">
<div class="wrapper">
<img src="http://placehold.it/150x300">
</div>
</div>
<hr/>
<div class="container">
<div class="wrapper">
<img src="http://placehold.it/1500x800">
</div>
</div>
Update
Added vertical-align: top; to image to fixed extra gap at bottom as pointed out by #TemaniAfif
Add image using background-image on wrapper element
.wrapper {
outline: 1px solid yellow;
background: url(http://via.placeholder.com/150x300);
background-size: cover;
width: 100%;
height: 100%;
background-repeat: no-repeat;
}
$(function() {
$('input[name=container-width]').on('change', function() {
$('.container').css('width', $(this).val() + 'px')
})
$('input[name=container-height]').on('change', function() {
$('.container').css('height', $(this).val() + 'px')
})
$('input[name=image-width]').on('change', function() {
var width = $(this).val()
var height = $('input[name=image-height]').val()
$('img')[0].src = 'http://via.placeholder.com/' + width + 'x' + height
})
$('input[name=image-height]').on('change', function() {
var height = $(this).val()
var width = $('input[name=image-width]').val()
$('img')[0].src = 'http://via.placeholder.com/' + width + 'x' + height
})
})
.container {
width: auto; /* can have any value in pixels */
height: auto; /* can have any value in pixels */
background-color: green;
}
.wrapper {
width: 100%;
height: 100%;
outline: 1px solid yellow;
}
.container > .wrapper > img {
width: 100%;
height: 100%;
opacity: .8;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Settings</h2>
Container: width <input type="number" step="10" name="container-width" value="200"> height <input type="number" step="10" name="container-height" value="200">
<br>
Image: width <input type="number" step="10" name="image-width" value="150"> height <input type="number" step="10" name="image-height" value="300">
<br>
<br>
<h2>Demo</h2>
<div class="container">
<div class="wrapper">
<img src="http://via.placeholder.com/150x300">
</div>
</div>
What about this ?
.container{
width: 200px;
height: 200px;
background-color: green;
}
.wrapper {
outline: 1px solid yellow;
height:100%;
}
img{
height: 100%;
}

Keeping side menu 100% height

I have a side menu which i would like to keep at 100% page height.
The code is basically just like this right now:
body,
html {
width: 100%;
height: 100%;
}
.sideMenu {
width: 200px;
height: 100%;
float: left;
}
The problem with this is that the side menus height does not extend with the rest of the page. For example I have input fields that can be added to a form, and when a few inputs have been added the form extends below the original view port. While the menu does not.
Heres a jsfiddle to demonstrate https://jsfiddle.net/m5yfqdsu/, click the "add row" button to add inputs until theyre below the viewport.
So what is the best solution to keep the menu at 100% height?
Prefer a CSS solution, but JS works as well if needed.
Add position: fixed; to .sideMenu
// just a quick function to add more inputs
$(document).ready(function() {
$(".add").on("click", function() {
$("fieldset").append("<div class='rowContainer'><label>Label:</label><input type='text' /></div>");
});
});
* {
margin: 0;
padding: 0
}
body,
html {
width: 100%;
height: 100%;
}
fieldset {
padding: 10px;
}
.sideMenu {
width: 200px;
height: 100%;
background-color: #1c1c1c;
position: fixed;
top: 0;
left: 0;
}
.wrapper {
margin-left: 200px;
}
input {
width: 100%;
max-width: 400px;
height: 40px;
display: block;
margin-bottom: 20px;
color: #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sideMenu"></div>
<div class="wrapper">
<h1>Page Title</h1>
<form>
<fieldset>
<div class="rowContainer">
<label>Label:</label>
<input type="text" />
</div>
<div class="rowContainer">
<label>Label:</label>
<input type="text" />
</div>
<div class="rowContainer">
<label>Label:</label>
<input type="text" />
</div>
</fieldset>
</form>
<button class="add">Add row</button>
</div>
You can solve this in multiple ways.
One way is to make a container having 100% height, making its child elements scrollable. That way you don't need the actual absolute rule, but it does achieve the same result. I prefer not using absolute because that makes it easier if you want it to be responsive eventually.
That way, you can scroll the sidebar and content seperatly. Both won't be bigger then they need to be. If the sidebar grows, it will be scrollable too.
* {
margin:0;
padding:0;
}
html, body, .wrapper {
height:100%;
}
.wrapper {
position:relative;
overflow-y:hidden;
}
.sidebar {
width:100px;
float:left;
height:100%;
overflow-y:auto;
background-color:red;
}
.content {
width:300px;
float:left;
height:100%;
overflow-y:auto;
background-color:blue;
}
.spacer {
height:1000px;
}
<div class="wrapper">
<div class="sidebar">
sidebar
</div>
<div class="content">
content
<div class="spacer">
spacer
</div>
</div>
</div>

Expand content div height to left-menu height when adding more item to menu

I have a left-menu in which I can add or remove item to. On the right there is a content div that has a min-height.
When adding more item into the left-menu using angular, I want the content div expand it height to the left-menu if the left-menu is taller than it's min-height.
One more thing is I also want the pull-down effect of ng-animate for the content div.
Here is the fiddle link: link
var app = angular.module('myApp', ['ngAnimate']);
app.controller('myCtrl', function($scope) {
$scope.items = ['foo', 'bar'];
var num = 0;
$scope.add = function() {
$scope.items.push(num);
num++;
}
});
#left {
width: 25%;
background-color: lightblue;
float: left;
}
#right {
width: 75%;
float: left;
background-color: lightgreen;
min-height: 200px
}
.item {
height: 20px;
opacity: 1;
transition: 0.5s;
}
.item.ng-enter {
opacity: 0;
height: 0;
}
.item.ng-enter-active {
height: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script src="https://code.angularjs.org/1.5.7/angular-animate.min.js"></script>
<div id="wrapper" ng-app="myApp" ng-controller="myCtrl">
<div id="left">
<p class="item" ng-repeat="item in items">
{{item}}
</p>
</div>
<div id="right">
<button ng-click="add()">add</button>
{{names}}
</div>
</div>
No need for hacky DOM manipulation using jQuery or ng-style. Just add display: flex to the wrapper:
#wrapper {
display: flex;
}
https://jsfiddle.net/babvqx8e/26/
Using flexbox also allows you to remove the floats:
#left {
width: 25%;
background-color: lightblue;
}
#right {
width: 75%;
background-color: lightgreen;
min-height: 200px
}
See this really nice guide to Flexbox for more info.
Use jQuery:
$("#right").css({'height': $("#left").outerHeight()});
It will set the height of #right to outer height of #left.
So I will answer my question. I managed to do it using the ng-style directive:
<div id="right" ng-style="{height: hgt+ 'px'}">
Then in the controller:
$scope.hgt = $('#left').outerHeight() + 40;
http://jsfiddle.net/babvqx8e/22/

css width of two items in a div to 100%

I have a page that looks like this jsfiddle, code below:
html:
<div class="parent">
<div class="child">
<input type="text">
<input type="submit">
</div>
</div>
css:
.parent { width: 500px; }
.child { width: 100%; }
How do I get it so that together they take up 100% of the parent div width (with the text input stretching accordingly)?
To clarify: I want the button(s) in a row to be fixed width and the input to take up the remaining width of the parent so that together the width = parent width. In the case that there are no button in the row, I'd like the textinput to take up the whole width.
.parent { width: 500px; margin:auto; }
.child { width: 100%; }
add this to make input stretches to full width
.child input { width: 100%; }
There are many ways to do this. One way to do this is to use the display:table-x attribute.
If you wrap the input elements in a div of their own like so:
<div class="parent">
<div class="text">
<input type="text" />
</div>
<div class="button">
<input type="submit" />
</div>
</div>
Then style the parent as display:table, the wrapper div's as display:table-cell, and give a width to div.button, like so:
.parent {
width: 500px;
background-color:blue;
display:table;
}
.text {
display:table-cell;
}
.text input {
width:100%;
-webkit-appearance:none;
}
.button {
display:table-cell;
background-color:red;
width:100px;
}
Then you can achieve the result you are looking for: http://jsfiddle.net/QpCCD/9/
This is similar to #panindra's post, but it keeps both inputs on the same line.
I've added some color to the sample to be able to see the position on the screen.
<html>
<head>
<style type="text/css">
body { background-color: black; }
.parent { width: 500px; background-color: white; text-align: center; }
.child { width: 100%; position: relative; margin: 0px 0px 0px 0px; border: 0px; }
.child input { width: 49%; margin: 0px 0px 0px 0px; border: 0px; }
</style>
</head>
<body>
<div class="parent">
<div class="child">
<input type="text">
<input type="submit">
</div>
</div>
</body>
</html>
Actually, this would be closer:
.child input { width: 248px; }

Getting an input to fill remaining width like a span element

I want to have a text input fill the horizontal space remaining in a div.
The answer here provides a simple example of doing this with a span: https://stackoverflow.com/a/3499333/165673, but for some reason I can't get my input element to behave in the same way.
HTML:
<div>
<span class="a">something</span>
<span class="b">fill the rest</span>
</div>
<div>
<span class="a">something</span>
<input class="b" value="fill the rest">
</div>
CSS:
.a {
float:left; background-color:red
}
.b {
background-color:green;display:block;
}
Fiddle: http://jsfiddle.net/FKZUA/1/
In the first example, span.b fills the remaining space. However, input.b won't.
This should do the trick for you:
css
.a {
display:table-cell; background-color:red;
}
.b {
display:table-cell; background-color:green; width:100%;
}
.c { width:100%; }
​
html
<div>
<span class="a">something</span>
<span class="b">fill the rest</span>
</div>
<div>
<span class="a">something</span>
<span class="b"><input class="c" value="fill the rest" /></span>
</div>
jsfiddle : http://jsfiddle.net/FKZUA/55/
You can use the ol' table display trick here. Lose the float and set the div to display: table; and the children to display: table-cell;.
Here's an example showing it. You may need some adjusting to the get the 'something' the way you want it (for instance, setting a width), but that might be more than what you want to do.
div {
display: table;
width: 100%;
}
.a, .b {
display: table-cell;
}
.b {
width: 100%;
}
css:
button.send {
float: right;
}
span.send {
display: block;
overflow: hidden;
}
input.send {
width:100%;
}
html:
<button type="button" id = "send_button" class="send" >SEND</button><span class="send"><input type="text" id = "newmessage" class="send" required></span>