Fill remaining width inside parent that is also filling remaining width - html

I have a fixed-size navbar (using Bootstrap) that contains four divs. These divs contain a logo, some links/dropdowns and a search box:
┌────────────────────────────navbar (fixed-size)──────────────────────────────┐
│┌───logo───┐┌───dropdown───┐┌───────────links──────────┐┌────search box─────┐│
││fixed-size││ fixed-size ││ variable width ││ fill remaining ││
│└──────────┘└──────────────┘└──────────────────────────┘└───────────────────┘│
└─────────────────────────────────────────────────────────────────────────────┘
I want the search box (the box on the far right) to fill the remaining space in the container. The search box comprises an input and a button:
┌─────────────────────────────────┐
│┌─────────────────────┐┌────────┐│
││ <input> ││<button>││
│└─────────────────────┘└────────┘│
└─────────────────────────────────┘
The button has a fixed size but I want the input to scale horizontally, stretching the search box to fill its parent (the nav-bar).
Edit: To clarify, I want the search box to take up the (horizontal) space left over from when it's siblings (logo, dropdown and links) have taken up their space. Since the search box is made out of an input and a button and the button will have a fixed width, I want the input to expand and push the search box's boundaries until the search box fills the space it's siblings left in the navbar

This is how I would do it: http://jsfiddle.net/vU52q/
You have your wrapper and child elements:
<div class="search">
<input type="text" />
<button type="submit">Go</button>
</div>
And you set the container to position: relative; and your submit button to position: absolute; and give the container enough padding for the button.
.search {
box-sizing: border-box;
background: #0f0;
padding: 5px 100px 5px 5px;
position: relative;
width: 300px;
}
.search input {
width: 100%;
}
.search button {
position: absolute;
top: 5px;
right: 5px;
width: 85px;
}
That way, the input is always the width of the parent element minus the width of the fixed width button.
You could also play with inline alignment and css calc, but this is my preferred way.
If you want to play with calc, you can check this out, and it might provide more of an option to add additional fixed size elements: http://jsfiddle.net/ug7a9/
This takes into account each section and explicitly adds it to the width calculation.
<div class="search">
<button type="submit">Go</button><!--
--><button type="submit">Go</button><!--
--><input type="text" /><!--
--><button type="submit">Go</button>
</div>
The comments are in there to prevent space in between elements (you can also do a font-size: 0) on the .search element.
* {
box-sizing: border-box;
}
.search {
background: #0f0;
position: relative;
width: 300px;
}
.search input {
display: inline-block;
width: calc(100% - 50px - 50px - 50px);
}
.search button {
display: inline-block;
width: 50px;
}
You'd want to be a bit more explicit with your selectors (i.e. don't do *), but for quick demo purposes I put this in.

you can use the calc function but not is cross-browser
calc(100% - element size);
http://jsfiddle.net/8CQHP/
You can see the support in caniuse.com

I ended up changing my code and using the idea from the solution Chad provided in the comment to his answer. I also used his absolute-positioned button trick. This is what I did:
I used a span for the search box and moved the button out of the search box straight into the nav:
<nav>
...
<span>
<input type="text" placeholder="Search...">
</span>
<button class="searchBtn" type="button"></button>
</nav>
Using this css:
span {
display: block; /*This is the trick from*/
overflow: hidden; /*the solution Chad provided*/
}
input {
width: 100%;
padding-right: 65px; /*This is to make room*/
} /*for the button*/
button {
position: absolute;
right: 0px;
top: 0px;
}
overflow: hidden on the span makes it all possible. Read about it here: http://colinaarts.com/articles/the-magic-of-overflow-hidden/#making-room-for-floats

Related

Fixed height input field on focus 'centers' the input

I have an input field where I add a fixed height. However, when I focus on said height, the height turns back to the original one...What I mean by that is that when I focus it, the 'area' where I write is in the center of the input field, while I want it at the bottom of the input field.
The reason why I want that is because I want a label inside the input field, so I increase the height of the input field, and stack the label behind the input field and have a transparent background on the input field. Here's the code and the demo on jsfiddle:
input {
position: absolute;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border-radius: 0;
width: 100%;
height: 7vh;
z-index: 10;
color: black;
background-color: transparent;
}
.test-label {
position: absolute;
left: 2%;
margin: 0;
top: 5%;
color: #778692;
}
.form-field {
height: 7vh;
position: relative;
padding: 0;
}
<div class="form-field">
<p class="test-label">Input</p>
<input type="text" />
</div>
How would I go to solve this?
I would probably add some padding to the top and include the
box-sizing: border-box;
So that your padding doesn't effect the size of the box.
The issue you will have, is your text's height is not dependant on the height of the view, whereas your input field is. So you will find inconsistent results on different height screens.
Here's an example JS fiddle:
http://jsfiddle.net/6uLnreu5/3/
Hope this helps
Use padding-top instead of fixed height. input {padding-top: 20px;}
you should define a font-size on your .test-label, and the set padding-top on the input equal to the font-size+x px where 0<=x<=somevalue as per your need of gapping between the label and text write area. Check out the fiddle - http://jsfiddle.net/6uLnreu5/7/
Additionally, you have to set box-sizing: border-box on the input so that its height does not increase beyond 10vh

How to add an image toward the right of a textbox and the text not overflowing to it

I have the following textbox:
<input type="text" id="fromAdd" class="styledTB searchBDir" />
CSS:
.styledTB {
padding-left: 5px;
background: #E8E8E8;
opacity: 1;
border: none;
outline: none;
right: 35px;
box-shadow:
0px 5px #BBB,
0px 8px 10px rgba(148, 148, 148, 0.5);
}
.searchBDir {
height: 30px;
width: 90%;
}
Displays this:
How can I add the following icon toward the right of the box and make it clickable for Geo Location:
To make something like this (I would like to resize the image to fit the textbox and not overlap as shown):
I am using the following script which will populate the textbox once the icon is clicked and the user gives permission:
$.get("http://ipinfo.io", function (response) {
$("{textboxid}").text("Location: " + response.city + ", " + response.region);
}, "jsonp");
Here's what we're doing
Some slight changes to HTML
<div class='styledTB'>
<input type="textbox" id="gpsInput" />
<button id="searchBDir"></button>
</div>
What we're doing here is giving some layout context for your input and button. The container is going to serve as our bounding box for laying out the remainder of our elements. You could accomplish this visually with only the input, but since you've got a clickable element it makes sense to make the clickable area a button (for accessibility, semantics, blah, blah, blah...).
On to the CSS:
.styledTB {
position: relative;
display: inline-block;
height: 40px; /* Arbitrary number */
width: 400px; /* Arbitrary number */
}
.styledTB input {
width: 100%; /* Arbitrary number */
height: 100%;
padding-right: 40px;
box-sizing: border-box;
}
#searchBDir {
height: 100%;
width: 40px; /* Or however long you'd like your button to be, matches padding-right above */
background-image: url(http://i.stack.imgur.com/4v62r.png);
background-repeat: no-repeat;
background-position: 50% 50%;
border: none;
background-color: transparent;
position: absolute;
right: 0;
top: 0;
}
Read the comments as they are helpful, but as a high-level overview:
We're putting the bounding box (the div) into a relative position so that we can order the button absolutely. We define the size we want our input element to appear (I chose some number arbitrarily, it should work similarly no matter what size you set them to) and set display inline-block to mirror that of a normal input element.
We then force the box to fill its container with the width and height being declared as 100% and give the box a padding-right of 40px to match our intended size for the button. We set the box-sizing to border-box so that the padding doesn't force the input larger than its containing box. This just tells the browser to consider padding, borders and all internal spacing elements to not grow the outer bounds of the element.
Lastly, we set the button to position: absolute and give it the positioning values to force it to the right of the box. We give it a background image of your GPS icon, and then position that appropriately within the button.
The border and background-color rules are there to override the default browser rendering of a button as a raised gray box.
I hope that helps!
Fiddle here
set the image as a background aligned to the right, and set the padding-right.

Collapsing margin alignment in Firefox

TLDR: this codepen works fine in Chrome, but the alignment is off in Firefox.
I'm building a jQuery plugin which modifies a text input to give it a dropdown button on the left. In order to get the positioning right, I add a wrapper div, which is the same height as the input, so the button can be absolutely positioned on top of the input, and yet still have the same height:
#wrapper {
position: relative;
}
#overlay {
position: absolute;
top: 0;
bottom: 0;
width: 30px;
}
This works fine until the input has vertical margin: then the container grows to include the margin, and so the dropdown button grows with it. My solution to this was margin collapsing: I gave the input display:block which meant that the container ignored it's margin. All good.
input {
margin: 20px 0 40px; /* testing */
display: block;
}
But now the problem is that by default, inputs are inline elements e.g. you might want to have a submit button next to the input. So I wrapped the whole thing in a container div with display:inline-block, so another inline element like a button can happily sit next to it.
#container {
display: inline-block;
}
This works fine in Chrome, but has weird alignment issues in Firefox when there's any vertical margin on the input. Below I've added the final markup. There's also a codepen link at the top.
<div id="container">
<div id="wrapper">
<input>
<div id="overlay"></div>
</div>
</div>
<button>Submit</button>
Edit: the point is that this is a plugin and I'm trying to work with the user's existing markup and CSS e.g. they have this markup:
<input><button>Submit</button>
and their existing CSS has vertical margin on the input, and I want them to be able to just initialise my plugin on the input and it just work, without forcing them to change their markup/CSS. Now because the plugin needs to add lots of markup around the input (for the overlay and the dropdown list), I wrap it all up in a container div. This container div is the limit of our reach (and does not include the button element, or anything else they choose to put next to their inputs).
To fix this, you'll need to define a line-height in your parent div#test2. Without it, different browsers will give it different values. This will cause Firefox to cause this weird result.
Now, the line-height isn't the only problem, also the vertical-align's baseline value will generate a different result for inline elements than it is for inline-block elements that have a different height than the surrounding inline content. To fix this, change the value to top for the #container element (since that's the inline-block element).
The final result would have the following changed (only pasting the parts that changed):
#test2 {
background-color: green;
line-height:70px;
#container {
// replicate the inline nature of the input
display: inline-block;
vertical-align:top;
}
//the rest of the #test2 nested code
}
That would look like this.
Reply to comment
I've made something that does work by the requirements set. Since you said the extra code (so the divs around the input) are made by the plugin itself, I've taken the liberty of changing that a bit to make this work.
The way it can work quite easily is just not using inline-blocks at all, and sticking with the inline elements. This would change the styles to the following:
#container {
// replicate the inline nature of the input
display: inline;
}
#wrapper {
display: inline;
position: relative;
}
input {
// you'll want to make sure the typed text doesn't appear behind the overlay
padding-left:35px;
}
#overlay {
position: absolute;
top: 0px;
bottom: 0px;
left: 1px;
width: 30px;
background-color: #00C2FF;
}
Notes:
I didn't bother making the overlay cover the full height of the input, since your plugin would just make it a flag anyway. To make it cover the full height, just set negative top and bottom styles on the overlay, equal to the computed padding-top and padding-bottom (resp.) on the input. In this case, you'd have to change them to top:-5px;bottom:-5px;. (you can get the computed style via jQuery's $(input).css('padding-top'))
You could actually also remove the whole #container from it, since the only style it has now is display:inline which really doesn't add anything to the whole thing.
I've added a padding-left to your input, because otherwise you'd have to type behind the overlay, which is just silly.
Is the HTML generated by the plugin and it needs to stay exactly the same? I'm not sure I can figure out exactly why the second example is not working, but you seem to have too many div elements there. You could make since simpler:
HTML
<div id="test1">
<div id="wrapper">
<input>
<div id="overlay"></div>
<button>submit</button>
</div>
</div>
SCSS
input, button {
border: 1px solid black;
padding: 5px;
}
input {
display: inline-block;
padding-left: 35px;
}
#test1 {
background-color: yellow;
padding: 20px 0 40px 0;
#wrapper {
position: relative;
#overlay {
position: absolute;
top: 1px;
left: 1px;
width: 30px;
background-color: #00C2FF;
}
}
}
Codepen example
I've removed the margin, and instead used padding on the parent, it achieves the same thing. You'll also want some padding-left on your input field so the entered text doesn't disappear behind your overlay div.
EDIT: In case you are unable to change the markup:
SCSS:
#test2 {
background-color: green;
#container {
// replicate the inline nature of the input
display: inline-block;
padding: 20px 0 40px 0;
}
#wrapper {
// this is just here to be display:block and ignore the margin on the input
display: block;
position: relative;
}
input {
// tell parent to ignore margin
//display: block;
margin: 0;
}
#overlay {
position: absolute;
top: 1px;
bottom: 1px;
left: 1px;
width: 30px;
background-color: #00C2FF;
}
}
codepen demo
Removed the block and margin declarations from the input field, and moved the spacing to padding of the #container element.
"Disclaimer": Let me just start by saying that I did not find exactly what is causing the problems in Firefox, but I did think of an alternative way you could do it.
The way this works in both Firefox and Chrome is just to use the exact same HTML as you used for your #test1, but on top of that, also using the CSS :before pseudo-element (instead of using the #container and #wrapper). The code I used was:
#test2 {
background-color: green;
position:relative;
&:before {
content:"";
display:block;
position:absolute;
left:1px;
top:1px;
bottom:1px;
margin:20px 0 40px 0;
width:30px;
background:#00C2FF;
}
}
demo
The way this works is to simply position the :before overlay on exactly the same place as the divs previously were. As you can see, I've used most of the same styles as you did, but instead, I've put them on the :before pseudo-class.
Other answers don't know why it doesn't work on Firefox. Well, I think that Firefox has the right behavior and it's a Chrome problem.
In short, you want to align an input with a button. But the input is inside a wrapper. Then, you can use vertical-align to control the vertical aligning between the wrapper and the button, but not between the input and the button.
Here you can see an screenshot with different vertical-align:
See the code.
If you want to align the input and the button (last case in the image), you have a problem, because any of the keywords you can use with vertical-align does that. Only in case that input's top margin and bottom margin are equal, then vertical-align: middle works.
But in general, you have have another solution: vertical-align also accepts a <length> value.
And, to get a perfect alignment, you should use the formula
vertical-align: -(input bottom margin)
Or, if you want to align them even if the button has a bottom margin, then
vertical-align: -(input bottom margin) + (button button margin)
The code formula above works with inline-block <div>, but not with <buttons>.
The formula must be fixed to
vertical-align: -(input bottom margin) -(input offsetHeight)/2 + 6
In your example
(Input bottom margin) = 40px
(Input offsetHeight) = 31px
Then, you need
vertical-align: -(input bottom margin) -(input offsetHeight)/2 + 6
Demo
I could achieve it with the following.Codepen You will have to know the css applied to input and apply it to button as well
button{
position:absolute;
margin-left:5px;
}
input, button {
display: inline-block;
margin: 20px 0 40px 0;
}
please update below in your code.
input, button {
border: 1px solid #000000;
margin: 20px 0 40px;
padding: 5px;
vertical-align: top;
}
hope it will work
http://codepen.io/anon/pen/Isycu

Fix left and right floating images in HTML

Here's what I'd like to do: have a banner across the top of a website which stretches all across. On the left is a menu, and on the right a logo image; the menu floats left, the image floats right.
The problem is the resizing of the browser window. Because the image floats right, it correctly moves as the window gets smaller. However, at some point it begins to float into the menu. Here is a Fiddle that illustrates this effect with two floating images. Resize the browser window to see how the two images overlap.
Setting
body {
min-width: 800px;
}
I can now make sure that the scrollbar appears as the browser window reaches a certain minimum width. However, that doesn't hinder the right-floating image to keep moving as the browser window keeps getting smaller. I tried to change position: relative but that didn't work. I tried to use Javascript to fixate the images once the browser window reaches its min-width but that didn't seem to have an impact either. Using min-width on the DIV and making the images children of the DIV didn't work either.
My question is: how can I make sure that, starting at a certain window size, the right-floating image stays put instead of floating into the left-floating menu?
EDIT: Oh dear, I forgot to mention a rather important detail: the menu bar at the top needs to be sticky. That is why I used the position: fixed property for the DIV. The other page content is supposed to scroll under that menu and out of the window, see the modified fiddle here which is based on ntgCleaner's answer. This kind-of changes the whole thing, doesn't it! Sorry about that...
Thanks!
A couple things I changed:
I made your banner DIV a container instead of just a free floating div. Probably not necessary.
I gave that banner div a min-width:280px and made it overflow:hidden;
I made the images just float left and right, not positioned relatively or absolute (since it's in the div container now).
#banner {
left: 0px;
top: 0px;
width: 100%;
height: 60px;
background-color: lightblue;
z-index: 1;
opacity: 0.8;
overflow:hidden;
min-width:280px;
}
#left {
float:left;
margin:5px;
height:40px;
}
#right {
float:right;
margin:5px;
height:40px;
}
​
​
Here's the fiddle
EDITED FOR THE EDITED QUESTION:
You will just need to place all of your content under your header into a div, then give that div a top margin of the height of your fixed div. In this caes, it's 60px.
Add this to your HTML
<div id="content">
this <br>
is <br>
some <br>
test <br>
text <br>
</div>
then add this to your CSS
#content {
margin:60px 0px 0px 0px;
}​
Here's the new fiddle
Is this what you are after? http://jsfiddle.net/9wNEx/10/
You are not using the position: fixed correctly. Fixed means 'positioned relative to the viewport or browser window', and that is exactly what you are experiencing.
I removed the position: fixed from the images, and placed them inside the div. This should keep them always on top of the page, as they are inside the div that is still positioned fixed.
Also I tweaked some of the other styling to replicate your example. Note that i removed the fixed height of the head and replaced it by a padding bottom. This way the height will follow the content whenever the screen size becomes to small and the images are forced underneath each other.
The css looks like this now:
#banner {
left: 0px;
top: 0px;
width: 100%;
padding-bottom: 15px;
background-color: lightblue;
z-index: 1;
position: fixed;
opacity: 0.8;
}
#left {
float: left;
margin-left: 10px;
margin-top: 5px;
height: 40px;
}
#right {
float: right;
margin-right: 10px;
margin-top: 5px;
height: 40px;
}
I changed your HTML to put the <img> tags inside the banner, and added the min-width to the #banner since it has position: fixed. You'll still need to add min-width to the body or a container that wraps all other elements if you want there to be a min-width of the entire page.
http://jsfiddle.net/Wexcode/s8bQL/
<div id="banner">
<img id="left" src="http://www.google.com/images/srpr/logo3w.png" />
<img id="right" src="http://www.google.com/images/srpr/logo3w.png" />
</div>
#banner {
width: 100%;
min-width: 800px;
height: 60px;
background-color: lightblue;
z-index: 1;
position: fixed;
opacity: 0.8; }
#left {
float: left;
margin: 5px 0 0 10px;
height: 40px; }
#right {
float: right;
margin: 5px 10px 0 0;
height: 40px; }
​
When I look at your Fiddle I think your problem isn't the floats at all. position:fixed supersedes float. Those two elements aren't floating at all, they're in a fixed position (similar to an absolute position), which is why they overlap when they don't have enough room.
Take out float:left and float:right, the result will be the same. Also, top, left, bottom, and right don't work on non-positioned elements. So they are superfluous on your banner.
If you use floats, however, when there is not enough room the right image will wrap underneath the left. See http://codepen.io/morewry/pen/rjCGd. Assuming the heights on the images were set for jsfiddle testing only, all you need is:
.banner {
padding: 5px; /* don't repeat padding unnecessarily */
min-width: ??; /* to keep floats from wrapping, set one */
overflow: hidden; /* clearfix */
}
.right { float: right; } /* only need one float, don't over-complicate it with two */

Label and input layout using css

I'm trying to line up a label and an input box on the same line in such a way that the label takes up all the space it needs and then the input box uses all of the remaining space. For example if the container was 1000px and the label was 342px then the input should be 658px wide. But if the label changed to 100px the input should resize to 900px. I could do this using a table layout, or using JavaScript to resize the input box when the label width changes but ideally I would like to do this using only css. My html looks like this.
<div id="container">
<label for="inputBox">variable text</label>
<input type="text" id="inputBox" />
</div>
Thanks,
Edit: To help illustrate what I'm trying to do here is an example using tables.
<table style="background-color:#ddd;width:500px;">
<tr>
<td style="width:0;white-space:nowrap;"><label style="width:100%">text</label></td>
<td><input style="width:100%" type="text" /></td>
</tr>
</table>
The correct way would be:
#container { width: 1000px; display: table }
#container label { display: table-cell; white-space: nowrap; }
#inputBox { width: 100%; display: table-cell; }
but that won't work in IE 6 or 7.
#container { margin-left: 100px; position: relative; }
#container label { position: absolute; left: -100px; }
#container input { width: 100%; }
(You can use box-sizing and its browser-specific versions to make sure the borders of the input line up nicely if necessary, and if you need that in IE6-7 too, a bunch of padding hacks to accomodate the extra pixels.)
This requires that the size of the label be known. It can't be made to depend on the width of the text content of label (ie ‘shrink-wrap’) without a bunch of extra markup (which wouldn't really be any better than using tables).
When liquid-layout forms get any more complicated than this, you do typically need to go to tables. Traditional CSS positioning isn't great at distributing widths between fixed, liquid, and shrink-wrap contents.
This CSS should work:
#container { width: 1000px; white-space: nowrap; }
#inputBox { width: 100%; }
Of course you can adjust the width of the container to suit your needs.
EDIT:
The above CSS expands the inputBox to be 1000px and therefore makes the div width greater than wanted.
To achieve the effect you want you can use the overflow property as described in http://www.stubbornella.org/content/2009/07/23/overflow-a-secret-benefit/ and a bit of an additional markup:
<div id="container">
<label for="inputBox">variable text</label>
<div><input type="text" id="inputBox" /></div> <!-- Notice the input is wrapped in an additional div -->
</div>
The CSS:
#container { width: 1000px; white-space: nowrap; }
#container label { float: left; margin-right: 5px; /* The label must be a floating element, the margin adds a little space to visually separate it from the input field */ }
#container div { overflow: hidden; /* This does the trick */ }
#inputBox { width: 100%; }