I am trying to create a control which contains two listboxes with add/remove buttons to move items from one list to the other. Typically I would do this using a table, but I am trying to follow css standards and use divs.
I have the listboxes aligned perfectly, but I can't figure out how to set up the buttons between them.
This is my html (updated to show rendered html):
<div id="dealsummary-ladderlist">
<form action="/Reporting/DealSummaryComparison" method="post">
<div id="available">
<div><strong>Available</strong></div>
<div id="available-items">
<select id="ItemsToSelect" multiple="multiple" name="ItemsToSelect" size="30">
<option value="16">Item 1</option>
<option value="17">Item 2</option>
<option value="21">Item 3</option>
<option value="22">Item 4</option>
<option value="23">Item 5</option>
<option value="24">Item 6</option>
<option value="25">Item 7</option>
</select>
</div>
</div>
<div id="add-remove">
<div><input type="button" value=">>" /></div>
<div><input type="button" value="<<" /></div>
</div>
<div id="selected">
<div><strong>Selected</strong></div>
<div id="selected-items">
<select id="ItemsToDeselect" multiple="multiple" name="ItemsToDeselect" size="30"></select>
</div>
</div>
<div style="clear:both;"></div>
<br /><br />
<center>
<p>
<input type="submit" value="Generate Report" />
</p>
</center>
</form>
</div>
This is what I have for css:
#add-remove {
/* want to center on page */
float: left;
width: 10%;
}
#add-remove div {
/* want to add even spacing between buttons */
}
#available {
float: left;
width: 45%;
}
#selected {
float: right;
width: 45%;
}
#available #available-items,
#selected #selected-items {
margin: 1em 0 0 0;
}
#available #available-items select,
#selected #selected-items select {
width: 100%;
font-size: 10pt;
}
How would I achieve the centering and even spacing of the arrow buttons using css?
If you know the precise width and height of the <div id="add-remove"> element, you could wrap the whole thing in a relatively-positioned <div> and use absolute positioning with negative margins like so:
<div id="relativeWrapper"> <!-- added this -->
<div id="available">
<!-- ... snip ... -->
</div>
<div id="add-remove">
<div><input type="button" value=">>" /></div>
<div><input type="button" value="<<" /></div>
</div>
<div id="selected">
<!-- ... snip ... -->
</div>
<div style="clear:both;"></div>
</div>
<!-- ... etc ... -->
With the CSS:
div#relativeWrapper {
position: relative;
}
div#add-remove {
position: absolute;
top: 50%;
left: 50%;
width: 80px;
margin-left: -40px;
height: 64px;
margin-top: -32px;
}
Setting both top and left to 50% and margin-left to half the value of width and margin-top to half the value of height will horizontally and vertically center an absolutely-positioned element within its relative parent.
Vertical-centering is difficult to achieve; you can use display: inline-block; vertical-align: middle;, but inline-block is not supported by all browsers. Alternatively, using display: table-cell; vertical-align: middle; tends to work.
Incidentally, the <center> element is deprecated. Use <div style="text-align: center;"> or simply <p style="text-align: center;"> instead.
Related
Semantically, my data is structured something like the following:
<div class="inputs">
<div class="top">
<h4>Top</h4>
<label for="top-1">Label 1</label>
<input id="top-1"/>
<label for="top-2">Label 2 is longer than the others</label>
<input id="top-2"/>
</div>
<div class="middle">
<h4>Middle</h4>
<label for="middle-1">Label 3</label>
<select id="middle-1">
<option value="middle-value-1">Value 1</option>
<option value="middle-value-2" selected>This is a longer value</option>
</select>
<label for="middle-2">Label 4</label>
<input id="middle-2"/>
</div>
<div class="bottom">
<h4>Bottom</h4>
<label for="bottom-1">Label 5</label>
<input id="bottom-1"/>
<label for="bottom-2">Label 6</label>
<input id="bottom-2"/>
</div>
</div>
I'd like to display these as distinct but related groups. For aesthetic purposes, I'd like to align and equally size all of the inputs and selects. Is it possible to do this without using explicit widths for everything? I greatly prefer to let things size themselves whenever possible.
Below is an implementation using display: grid with fixed widths for the columns and the grid itself. Is there any way to do this with dynamic sizes?
I'm not stuck on display: grid, by the way. It's just the simplest solution I've come up with so far. I like that it helps keep my HTML simple and semantic. I can use display: table just as well if I nest the labels and inputs in a div with display: table-row. But I still can't let things size dynamically, unless I flatten it by removing the top, middle, and bottom divs.
.inputs > div {
display: grid;
grid-template-columns: 13em 10em;
width: 24em;
gap: 0.5em;
padding: 0.5em;
}
.inputs label {
grid-column: 1;
}
.inputs select, .inputs input {
grid-column: 2;
}
.inputs h4 {
grid-column: 1 / span 2;
margin: 0;
}
.top, .bottom {
background-color: #c0c0c0;
}
.middle {
background-color: #e0e0e0;
}
.middle, .bottom {
margin-top: 0.5em;
}
<div class="inputs">
<div class="top">
<h4>Top</h4>
<label for="top-1">Label 1</label>
<input id="top-1"/>
<label for="top-2">Label 2 is longer than the others</label>
<input id="top-2"/>
</div>
<div class="middle">
<h4>Middle</h4>
<label for="middle-1">Label 3</label>
<select id="middle-1">
<option value="middle-value-1">Value 1</option>
<option value="middle-value-2" selected>This is a longer value</option>
</select>
<label for="middle-2">Label 4</label>
<input id="middle-2"/>
</div>
<div class="bottom">
<h4>Bottom</h4>
<label for="bottom-1">Label 5</label>
<input id="bottom-1"/>
<label for="bottom-2">Label 6</label>
<input id="bottom-2"/>
</div>
</div>
I found a solution with display: table. It's a little uglier than the grid solution and not quite as semantic as I'd like, but it's close, and it does what I want.
.inputs {
display: table;
border-collapse: collapse;
}
.inputs > .top, .inputs > .bottom {
display: table-row-group;
background-color: #c0c0c0;
}
.inputs > .middle {
display: table-row-group;
background-color: #e0e0e0;
}
.input {
display: table-row;
}
.input > * {
display: table-cell;
}
.input > h4, .input > label {
padding: 0.5em 0.25em 0 0.5em;
}
.input > select, .input > input {
margin: 0 0.5em 0.25em 0;
box-sizing: border-box;
width: calc(100% - 0.5em);
}
.input:last-child > * {
margin-bottom: 0.5em;
}
.padding {
padding: 0.5em 0;
}
<div class="inputs">
<div class="top">
<div class="input">
<h4>Top</h4>
<div class="empty"></div>
</div>
<div class="input">
<label for="top-1">Label 1</label>
<input id="top-1"/>
</div>
<div class="input">
<label for="top-2">Label 2 is longer than the others</label>
<input id="top-2"/>
</div>
</div>
<div class="input">
<div class="padding"></div>
</div>
<div class="middle">
<div class="input">
<h4>Middle</h4>
<div class="empty"></div>
</div>
<div class="input">
<label for="middle-1">Label 3</label>
<select id="middle-1">
<option value="middle-value-1">Value 1</option>
<option value="middle-value-2" selected="selected">This is a longer value</option>
</select>
</div>
<div class="input">
<label for="middle-2">Label 4</label>
<input id="middle-2"/>
</div>
</div>
<div class="input">
<div class="padding"></div>
</div>
<div class="bottom">
<div class="input">
<h4>Bottom</h4>
<div class="empty"></div>
</div>
<div class="input">
<label for="bottom-1">Label 5</label>
<input id="bottom-1"/>
</div>
<div class="input">
<label for="bottom-2">Label 6</label>
<input id="bottom-2"/>
</div>
</div>
</div>
You can set your grid up more dynamically with something like this:
.inputs {
width: 33%;
min-width: 25em;
}
.inputs > div {
display: grid;
grid-template-columns: 1.3fr 1fr;
gap: 0.5em;
padding: 0.5em;
}
I used your outer container to deal with the width as it relates to the screen. The hard min-width of 25px keeps the long label from wrapping to another line, instead showing a horizontal scrollbar if the screen size causes 33% of the width to go below 25px.
For your inner containers, you can change the unit in grid-template-columns to fr, which means fraction of available space. This will let your columns dynamically size along with your window (until you hit the min-width for the outer container). You can experiment with the width percentage to work out just how much dynamic sizing you would like to do.
This is a good writeup of fr if you would like one.
Have the following css to set the background image on a single page app (Angular)
.page::before {
content: '';
position: absolute;
background-size: cover;
width: 100%;
height: 100%;
background-image: url("../../assets/weird.png");
opacity: 0.2;
}
...
/* button */
#submit-button {
position: center;
background: #000000;
border-radius: 5px;
font-size: 15px;
padding: 15px 15px 15px 15px;
margin: -15px 15px 15px 15px;
color: white
}
Here is the html:
<div class="page">
<h1 class="sunrise">Asheville Ipsum</h1>
<h2 class="sunrise">Asheville Infused Lorem Ipusm Generator</h2>
<h3 class="sunrise">Ditch that boring ipsum for some auto-generated, beer infused,</h3>
<h3 class="sunrise">funky smelling, hippster weirdness.</h3>
<div class="inputs">
<form [formGroup]="registerForm" (ngSubmit)="onSubmit()">
<div class="form-group" id="short-medium-long">
<mat-radio-group aria-label="Select an option" formControlName="numberOfWords" class="form-control" >
<mat-radio-button value="50">Short</mat-radio-button>
<mat-radio-button value="75">Medium</mat-radio-button>
<mat-radio-button value="100">Long</mat-radio-button>
</mat-radio-group>
</div>
<div class="form-group" id="numberOfParagraphs">
<label>Number of Paragraphs</label>
<input type="number" id="number-field" formControlName="numberOfParagraphs" class="form-control" />
<mat-checkbox formControlName="moreBeer" class="form-control">More Beer!</mat-checkbox>
</div>
<div class="form-group">
<button class="btn btn-primary" id="submit-button">Generate Weirdness</button>
</div>
</form>
</div>
<div class="content" *ngFor="let paragraph of paragraphs">{{ paragraph }}<br><br></div>
</div>
With this css added the submit button no longer works. No console error or anything. Also, I can remove the content or position attributes and it works fine through the background image no longer displays.
I feel like something in the css must be in conflict?
I am sure there is no such thing called position: center;.
All of these are the available properties which can be used with position: position:static|absolute|fixed|relative|sticky|initial|inherit;
Changing that CSS property will help you out.
Trying to create a layout that has two columns, and text between those columns
Something like this:
But I am running into spacing issues with twitter bootstrap to make it actually work. On top of making these items the same width with the text between, they should all be vertically aligned.
You can do that using 3 columns
Live Demo jsfiddle
<div class="container-fluid">
<div class="row">
<div class="col-xs-6">.col-sm-6</div>
<div class="col-xs-6">.col-sm-6</div>
</div>
<br/>
<p>Create an account...............................</p>
<div class="row">
<div class="col-xs-6 test" >
<form class="form-horizontal vmid" role="form">
<div class="form-group">
<label class="control-label col-sm-2" for="email">Email:</label>
<div class="col-sm-10">
<input type="email" class="form-control" id="email" placeholder="Enter email"/>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="pwd">Password:</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="pwd" placeholder="Enter password"/>
</div>
</div></form>
</div>
<div class="col-xs-1 test" >
<p class="asd"> ~OR~</p>
</div>
<div class="col-xs-5 test" >
<button type="submit" class="asd btn-primary btn-lg">Facebook</button>
</div>
</div>
</div>
Style
.vmid{
position:relative;
top:50%;
transform:translateY(-50%);
}
.asd{
position:relative;
top:50%;
transform:translateY(-35%);
}
This is not a bootstrap answer just a plain simple CSS one. Although you can adapt it to bootstrap easily because the basic underlying principle is the same. Instead of using width percentages that I have used in my example, bootstrap grid system columns can be used instead. Saying all that, you can achieve your desired effect by dividing the wrapper div into 3 columns and then using the display table for parent and table-cell and vertical align middle for the child to place the respective input elements and button elements in its place as needed.
The fiddle can be found here
The code snippet follows...
.wrapper {
height: 300px;
width: 100%;
background: pink;
}
.leftSide,
.rightSide,
.midPart {
box-sizing: border-box;
height: 100%;
display: table;
}
.leftSide {
width: 45%;
background: lightgray;
float: left;
}
.midPart {
width: 10%;
background: aqua;
}
.midPart p {
display: table-cell;
vertical-align: middle;
text-align: center;
}
.leftSide div,
.rightSide div {
display: table-cell;
vertical-align: middle;
text-align: center;
}
.rightSide {
width: 45%;
background: lightcyan;
float: right;
}
button {
height: 3em;
width: 100px;
background: blue;
color: white;
}
<div class="wrapper">
<div class="leftSide">
<div>
<input placeholder="Enter Username" />
<br/>
<br/>
<input placeholder="Enter password" />
</div>
</div>
<div class="rightSide">
<div>
<button>Hello</button>
</div>
</div>
<div class="midPart">
<p>-or-</p>
</div>
</div>
Hope this helps. Happy coding :)
Update::
***Another updated Fiddle without colors***
I have a series of inline divs that aren't wrapping correctly. As the browser is resized, the divs should be aligning flush left but sometimes they are flush right. I've read several articles on this but they don't seem to be the same issue. Any help would be much appreciated. My jsfiddle is http://jsfiddle.net/7uuLaLg4/.
<style type="text/css">
.box
{
float: left;
border: 1px solid black;
}
.address .item
{
display: inline;
float: left;
}
</style>
<div class="box">
<div class="address">
<div class="item">
<div>Address (Number & Road) <label class="required">*</label></div>
<div><input id="User_Address_Address1" name="User.Address.Address1" style="width: 13em;" type="text" value="1 Main St." /></div>
</div>
<div class="item">
<div>Address 2 (APT, Suite...)</div>
<div><input id="User_Address_Address2" name="User.Address.Address2" type="text" value="" /></div>
</div>
<div class="item">
<div>City<label class="required">*</label></div>
<div><input id="User_Address_City" name="User.Address.City" type="text" value="Anytown" /></div>
</div>
<div class="item">
<div>State<label class="required">*</label></div>
<div>
<select id="User_Address_StateID" name="User.Address.StateID">
<option selected="selected" value="3">Kentucky</option>
</select>
</div>
</div>
<div class="item">
<div>Zip<label class="required">*</label></div>
<div><input class="zip-mask" id="User_Address_Zip" maxlength="5" name="User.Address.Zip" style="width: 5em;" type="text" value="12345" /></div>
</div>
<div class="item">
<div>County<label class="required">*</label></div>
<div>
<select id="User_Address_CountyID" name="User.Address.CountyID">
<option value="0"></option>
<option selected="selected" value="125542">Campbell</option>
</select>
</div>
</div>
<div class="item">
<div>Country<label class="required">*</label></div>
<div>
<select id="User_Address_CountryID" name="User.Address.CountryID">
<option value="0"></option>
<option selected="selected" value="1">United States</option>
</select>
</div>
</div>
</div>
</div>
Here is fixed example.
http://jsfiddle.net/7uuLaLg4/2/
.box{
border: 1px solid black;
text-align: left;
}
.address .item{
display: inline-block;
margin: 0 0 10px 0;
}
They are not all the same height which is why sometimes they act like they are floating right.
Something like min-height: 60px; should help.
.address .item {
display: inline-block;
min-height: 60px;
}
http://jsfiddle.net/bb1ooguo/1/
I have a couple of different issues.
I have a div with a couple of other divs and some controls in it. My biggest issue is that it does not look the same in Chrome as it does in other browsers. As it is right now, it looks as following:
And the biggest issue is with Chrome, where the textbox to the right of the "width:" text goes down onto the next line. The code for the box can be seen in this JSFiddle or as as following:
<div id="div_properties" class="redBorder left" style="clear: left; display:
<div class="right">
<a href="#" id="closePropertiesWindow">
<img src="close.png" title="Close window"></a>
</div>
<div class="centered noMargin whiteBackground">
<h3 class="noMargin">Properties</h3>
</div>
<hr class="noMargin noPadding">
<div id="div_properties_content" style="display: block;">
<div class="noMargin propertiesControl" prop="text" style="width:100%;">
text:
<input type="text" id="propertytextTextBox" class="right"></input>
</div>
<div class="noMargin propertiesControl" prop="width" style="width:100%;">
width:
<input type="number" id="propertywidthNumber" class="right"></input>
</div>
<div class="noMargin propertiesControl" prop="italic" style="width:100%;">
italic:
<input type="checkbox" id="propertyitalicCheckBox" class="right" checked="checked">
</div>
<div class="noMargin propertiesControl" prop="bold" style="width:100%;">
bold:
<input type="checkbox" id="propertyboldCheckBox" class="right">
</div>
<br>
<input type="button" id="savePropertiesButton" value="Save" class="right">
</div>
</div>
And the CSS is as following:
#div_properties {
margin-top: 5px;
background-color: #F0F0F0;
width: 300px;
float: left;
min-height: 75px;
}
.redBorder {
border: 1px solid red;
}
.noMargin {
margin: 0 0 0 0;
}
.left {
float: left;
}
.right {
float: right;
}
(Those are all the related classes in this scope, the other classes defined on the items have no styles, but are being used in the JavaScript.)
Also, another issue I'm having is the "box border" around the close-image in IE. This is not a big issue, but if anyone knows what is causing it, it would be fantastic.
Its the floating that's causing the issue. You need to clear them.
.propertiesControl {
clear:both;
}
http://jsfiddle.net/JWDkM/2/