How do I have focus effect on normal elements? - html

I am using CSS grid to display some tabular data as shown in example
https://codepen.io/shyamforflex/pen/qBrLQeq
On row selection , the selected row should have a background color.
In current example the background red color is disappearing on mouse click release
&-row:active {
background-color: red;
}

You could use a radio button hack. Add a hidden radio button to each row. Change your "cells" to label associated with the radio button then use type=[radio]:checked ~ label to apply the styling. While the HTML is perfectly valid, the use of input here is semantically questionable at best.
From your pen you would want something like
PUG
each episode in episodes
.grid-table-row
input(type="radio" name="tbl" id=episode.series +"|"+episode.no)
label.grid-table-cell(data-title="Title" for=episode.series +"|"+episode.no)= episode.title
label.grid-table-cell(data-title="Number" for=episode.series +"|"+episode.no)= episode.no
label.grid-table-cell(data-title="Series" for=episode.series +"|"+episode.no)=episode.series
label.grid-table-cell(data-title="Air Date" for=episode.series +"|"+episode.no)= episode.airdate
SCSS
.grid-table {
display: grid;
/*Additional code removed for brevity*/
input[type=radio] {display:none}
input:checked ~ label {
background-color: red;
}
}
Compiled Demo:
h1 {
text-align: center;
}
input[type=radio] {
display: none;
}
.grid-table {
display: grid;
}
.grid-table-row {
display: grid;
grid-template-columns: repeat(2, 2fr) repeat(2, 1fr);
border-bottom: 1px solid #ddd;
}
.grid-table-row:first-child {
background: rgba(0, 0, 0, 0.5);
font-weight: bold;
}
.grid-table-row:hover {
background-color: yellow;
cursor: pointer;
}
.grid-table input:checked~label {
background-color: red;
}
.grid-table-row:nth-child(even) {
background-color: #e5e4e2;
}
.grid-table-cell {
padding: 1rem;
}
.grid-table-cell:not(:last-child) {
border-right: 1px solid #ddd;
}
<h1>Random Dr Who Tabular Data With CSS Grid</h1>
<div class="grid-table">
<div class="grid-table-row">
<div class="grid-table-cell">Title</div>
<div class="grid-table-cell">Episode Number</div>
<div class="grid-table-cell">Series</div>
<div class="grid-table-cell">Air Date</div>
</div>
<div class="grid-table-row">
<input type="radio" name="tbl" id="7|239" />
<label class="grid-table-cell" data-title="Title" for="7|239">The Name of the Doctor</label>
<label class="grid-table-cell" data-title="Number" for="7|239">239</label>
<label class="grid-table-cell" data-title="Series" for="7|239">7</label>
<label class="grid-table-cell" data-title="Air Date" for="7|239">05/18/2013</label>
</div>
<div class="grid-table-row">
<input type="radio" name="tbl" id="Special|1" />
<label class="grid-table-cell" data-title="Title" for="Special|1">The Day of the Doctor</label>
<label class="grid-table-cell" data-title="Number" for="Special|1">1</label>
<label class="grid-table-cell" data-title="Series" for="Special|1">Special</label>
<label class="grid-table-cell" data-title="Air Date" for="Special|1">11/23/2013</label>
</div>
<div class="grid-table-row">
<input type="radio" name="tbl" id="Special|2" />
<label class="grid-table-cell" data-title="Title" for="Special|2">The Time of the Doctor</label>
<label class="grid-table-cell" data-title="Number" for="Special|2">2</label>
<label class="grid-table-cell" data-title="Series" for="Special|2">Special</label>
<label class="grid-table-cell" data-title="Air Date" for="Special|2">11/25/2013</label>
</div>
<div class="grid-table-row">
<input type="radio" name="tbl" id="Special|3" />
<label class="grid-table-cell" data-title="Title" for="Special|3">The Salary of the Doctor</label>
<label class="grid-table-cell" data-title="Number" for="Special|3">3</label>
<label class="grid-table-cell" data-title="Series" for="Special|3">Special</label>
<label class="grid-table-cell" data-title="Air Date" for="Special|3">6/25/2015</label>
</div>
</div>

:focus can work for what you want to achieve only if the element is an focusable element such as anchor link or inputs. Please refer to the MDN for more information.
Solution
There is a way to add focusability to normal elements. Set tabindex to each row so that the elements become focusable.
Set tabindex to .grid-table-row
each episode in episodes
.grid-table-row(tabindex="0")
Replace &-row:active with below
&-row:focus {
background-color: red;
}
However, this method should only be used for web accessbility, which means only the interactive elements should be focusable.

Related

Show/hide content on checkbox

i want to hide all content, i want them to show when checked
like show content when checkbox checked
hide when unchecked so that when i check others they show up too
here is my try but its not working
<style>
#myBike:not(:checked) +#bike {
display: block !important;
}
#myCar:not(:checked) +#car {
display: block !important;
}
</style>
<input type="checkbox" id="myBike">
<label for="vehicle1"> I have a bike</label><br>
<input type="checkbox" id="myCar">
<label for="vehicle2"> I have a car</label><br>
<div class="row" id="bike">
Something for bike
</div>
<div class="row" id="car">
Something for car
</div>
Please check the code below.
#bike {
display: none;
}
#myBike:checked~#bike {
display: block;
}
#car {
display: none;
}
#myCar:checked~#car {
display: block;
}
<input type="checkbox" id="myBike" />
<label for="vehicle1">I have a bike</label>
<input type="checkbox" id="myCar" />
<label for="vehicle2">I have a car</label>
<div class="row" id="bike">Something for bike</div>
<div class="row" id="car">Something for car</div>
Expanation:
You have used a wrong syntax ~ vs +
By default all div are set as display:block. You should set display:none as its initial.

Css Grid Can't Affect Input Items

I'm learning css grid and i'm trying to arrange a page with inputs and other stuff.
Nothing works for some reason and i can't figure out what the problem is.
The form doesn't show any reaction, doesn't move at all.
Here's the html code:
<div className="shipment-page">
<div className="shipment-form">
<form onSubmit={this.handleSubmit}>
<div className="first-input">
<label className="sp-input-label" htmlFor="first_name">First Name</label>
<input
type="text"
name='first_name'
className="sp-input first"
value={this.state.first_name}
onChange={this.handleChange}
required
/>
</div>
<div className="second-input">
<label className="sp-input-label" htmlFor="last_name">Last Name</label>
<input
type="text"
name='last_name'
className="sp-input second"
value={this.state.last_name}
onChange={this.handleChange}
required
/>
</div>
<div className="third-input">
<label className="sp-input-label" htmlFor="address">Address</label>
<input
type="text"
name='address'
className="sp-input"
value={this.state.address}
onChange={this.handleChange}
required
/>
</div>
<div className="fourth-input">
<label className="sp-input-label" htmlFor="Zip Code">Zip Code</label>
<input
type="number"
name='zip_code'
className="sp-input"
value={this.state.zip_code}
onChange={this.handleChange}
required
/>
</div>
<div className="fifth-input">
<label className="sp-input-label" htmlFor="phone_number">Phone Number</label>
<input
type="number"
name='phone_number'
className="sp-input"
value={this.state.phone_number}
onChange={this.handleChange}
required
/>
</div>
<div className="check-current-address">
<label htmlFor="current_address">Is this your current address? </label>
<input
type="radio"
name="current_address"
value={true}
onChange={this.handleChange}
required
/><span>Yes</span>
<input
type="radio"
name="current_address"
value={false}
onChange={this.handleChange}
required
/><span>No</span>
</div>
<CustomButton type='submit'>Add Address</CustomButton>
</form>
</div>
<span className="progress-indicator">
<StepProgress/>
</span>
</div>
and here's the sass code:
.shipment-page{
margin: 100px;
display: grid;
grid-template-columns: repeat(2, minmax(375px, 1fr)) minmax(300px, 1fr);
grid-template-rows: repeat(6, 50px) 1fr;
grid-template-areas:
"first second info-box"
"third third info-box"
"fourth fifth info-box"
"check . ."
"buttons . ."
"progres progres progres";
.shipment-form{
grid-row: 1/6;
grid-column: 1/3;
.first-inputs{
grid-area: first;
}
.second-inputs{
grid-area: second;
}
.third-inputs{
grid-area: third;
}
.fourth-inputs{
grid-area: fourth;
}
.fifth-inputs{
grid-area: fifth;
}
.sp-input{
background: none;
background-color: white;
color: grey;
font-size: 18px;
padding: 10px 10px 10px 5px;
width: 100%;
border: none;
border-radius: 0;
border-bottom: 1px solid grey;
&:focus{
outline: none;
color: black;
border-bottom: 1px solid black;
}
}
.check-current-address{
margin-bottom: 25px;
}
}
.progress-indicator{
grid-area: progres;
}
}
how the page looks like now
how it should look like
Help.
The form isn't responding the way you expect because only direct grid children matter (just like with flexbox). .shipment-form is a valid grid child because it's one level deep from the grid parent, .shipment-page.
<div className="shipment-page"> <!-- grid parent -->
<div className="shipment-form"> <!-- grid child -->
<form onSubmit={this.handleSubmit}> <!-- too deep—not a grid child -->
Try to restructure your code so that the grid parent is one level above your form input containers. Also, you have a potential bug in your code. Your CSS is referencing the plural inputs but your HTML class is using the singular input
<div className="first-input">
And then:
.first-inputs{ ... } /* Oops, that class does not exist in your HTML */

Add '*' to the label of input fields with the 'required' attribute with CSS

I am wondering if there is a way using only CSS to add an asterisk to a label element when the label's for attribute is for an input element with a required html attribute. Alternatively, we could use logic around if the label is directly followed by an input element which has the required attribute.
What does work is something like this:
input[required] + label:after {
content: '*';
color: red;
}
<form>
<div>
<input for="name" type="text" required />
<label id="name">Name</label>
</div>
<div>
<input for="age" type="text" />
<label id="age">Age</label>
</div>
</form>
But what I'm talking about is if the label and input are swapped around like the example below, which is more common. The CSS sibling selector + doesn't work for this case. Is there any way to do some like above when the label element is first and the input is second?
/* ??? */
<form>
<div>
<label for="name">Name</label>
<input id="name" type="text" required />
</div>
<div>
<label for="age">Age</label>
<input id="age" type="text" />
</div>
</form>
Thanks
I suggest you keep old html and use css flex to order position
input[required] + label:after {
content: '*';
color: red;
}
div {
display: flex;
text-align: center;
align-items: flex-start;
}
div input {
width: 100px;
height: 20px;
order: 2;
}
div label {
width: 100px;
height: 20px;
order: 1;
}
<form>
<div>
<input for="name" type="text" required />
<label id="name">Name</label>
</div>
<div>
<input for="age" type="text" />
<label id="age">Age</label>
</div>
</form>
See the codepen
You can use float for label to positining label at left like below:
label {
float: left;
}
input[required] + label:after {
content: '*';
color: red;
}
}
<form>
<div>
<input for="name" type="text" required />
<label id="name">Name</label>
</div>
<div>
<input for="age" type="text" />
<label id="age">Age</label>
</div>
</form>
There is no way for CSS to "render backwards" the way you want it too (not without SASS/SCSS).
One solution would be to add a "required" class to the labels that correspond to required fields.
<style>
label.required:after { content: '*';color:red; }
</style>
<form>
<div>
<label for="name" class="required">Name</label>
<input id="name" type="text" required />
</div>
<div>
<label for="age">Age</label>
<input id="age" type="text" />
</div>
</form>
Another option is the use of CSS3 Orders property, but the parent element would need to be set to "display:flex".
<style>
div { display:-webkit-flex;display:flex; }
div label { order:1; }
div input { order:2; }
div input[required] + label:after { content: '*';color:red; }
</style>
<form>
<div>
<input id="name" type="text" required />
<label for="name">Name</label>
</div>
<div>
<input id="age" type="text" />
<label for="age">Age</label>
</div>
</form>
EDIT 6/25/2019 SASS/SCSS Example
div {
display:-webkit-flex;
display:flex;
label {
order:1;
}
input {
order:2;
&[required] + label:after {
content: '*';color:red;
}
}
}
More information about Parent Selectors in SCSS.

Tab content not showing up

I am creating tabs using CSS only. The way it works is, there are 3 radio buttons, and a label for each radio button. The tab contents are set to display: none. When a tab gets selected, then that tab contents become display: block
Since there were white spaces separating the labels (tabs) I added a div around the input/label elements and used the Flexbox technique.
Now that I added the div around the inputs/labels, the tab contents never show, they never become display: block.
How can I make the tab contents show when a tab gets selected?
Here's the relevant code:
.tab1:checked ~ .tab1,
.tab2:checked ~ .tab2,
.tab3:checked ~ .tab3 {
display: block;
}
Working, but with white space
JSFiddle
.tab {
background-color: yellow;
display: inline-block;
width: calc(100% / 3);
height: 50px;
outline: 1px green solid;
}
.tabContent,
input {
display: none;
}
.tab1:checked ~ .tab1,
.tab2:checked ~ .tab2,
.tab3:checked ~ .tab3 {
display: block;
}
<div id="overallDiv">
<input type="radio" name="tabGroup1" id="rad1" class="tab1" checked="checked" />
<label for="rad1" class="tab">Fisrt Tab</label>
<input type="radio" name="tabGroup1" id="rad2" class="tab2" />
<label for="rad2" class="tab">Second Tab</label>
<input type="radio" name="tabGroup1" id="rad3" class="tab3" />
<label for="rad3" class="tab">Third Tab</label>
<div class="tabContent tab1" id="first">
First Tab
</div>
<div class="tabContent tab2" id="second">
Second Tab
</div>
<div class="tabContent tab3" id="third">
Third Tab
</div>
</div>
Not Working, but now white spaces
JSFiddle
.tab {
background-color: yellow;
display: inline-block;
width: calc(100% / 3);
height: 50px;
outline: 1px green solid;
}
.tabContent,
input {
display: none;
}
.tab1:checked ~ .tab1,
.tab2:checked ~ .tab2,
.tab3:checked ~ .tab3 {
display: block;
}
<div id="overallDiv">
<div id="tabWrapper" style="display: flex;">
<input type="radio" name="tabGroup1" id="rad1" class="tab1" checked="checked" />
<label for="rad1" class="tab">Fisrt Tab</label>
<input type="radio" name="tabGroup1" id="rad2" class="tab2" />
<label for="rad2" class="tab">Second Tab</label>
<input type="radio" name="tabGroup1" id="rad3" class="tab3" />
<label for="rad3" class="tab">Third Tab</label>
</div>
<div class="tabContent tab1" id="first">
First Tab
</div>
<div class="tabContent tab2" id="second">
Second Tab
</div>
<div class="tabContent tab3" id="third">
Third Tab
</div>
</div>
As inline element have a space margin, your div becomes a little bigger than 33% and therefore doesn't fit in 1 row.
To your Working, but with white space sample I added margin-right: -4px; re-ordered your html a little to take that space out, but this can be done using other hacks, floats and flex. (for floats/flex, see below)
The trick in this case is to make the inline elements stop and start tag to be on the same line like this: </label><label
Note: These margin space issues has already been solved before
How to remove the space between inline-block elements?
Why is there an unexplainable gap between these inline-block div elements?
.tab {
background-color: yellow;
display: inline-block;
width: calc(100% / 3);
height: 50px;
outline: 1px green solid;
}
.tabContent,
input {
display: none;
}
.tab1:checked ~ .tab1,
.tab2:checked ~ .tab2,
.tab3:checked ~ .tab3 {
display: block;
}
<div id="overallDiv">
<input type="radio" name="tabGroup1" id="rad1" class="tab1" checked="checked" />
<input type="radio" name="tabGroup1" id="rad2" class="tab2" />
<input type="radio" name="tabGroup1" id="rad3" class="tab3" />
<label for="rad1" class="tab">First Tab
</label><label for="rad2" class="tab">Second Tab
</label><label for="rad3" class="tab">Third Tab
</label>
<div class="tabContent tab1" id="first">
First Tab
</div>
<div class="tabContent tab2" id="second">
Second Tab
</div>
<div class="tabContent tab3" id="third">
Third Tab
</div>
</div>
As requested a flex version.
#overallDiv {
display: flex;
flex-wrap: wrap;
}
.tab {
background-color: yellow;
width: calc(100% / 3);
height: 50px;
outline: 1px green solid;
}
.tabContent,
input {
display: none;
}
.tabContent {
width: 100%;
}
.tab1:checked ~ .tab1,
.tab2:checked ~ .tab2,
.tab3:checked ~ .tab3 {
display: block;
}
<div id="overallDiv">
<input type="radio" name="tabGroup1" id="rad1" class="tab1" checked="checked" />
<label for="rad1" class="tab">Fisrt Tab</label>
<input type="radio" name="tabGroup1" id="rad2" class="tab2" />
<label for="rad2" class="tab">Second Tab</label>
<input type="radio" name="tabGroup1" id="rad3" class="tab3" />
<label for="rad3" class="tab">Third Tab</label>
<div class="tabContent tab1" id="first">
First Tab
</div>
<div class="tabContent tab2" id="second">
Second Tab
</div>
<div class="tabContent tab3" id="third">
Third Tab
</div>
</div>
Edit
Here is a "floats" version
#overallDiv {
clear: left;
}
.tab {
background-color: yellow;
float: left;
width: calc(100% / 3);
height: 50px;
outline: 1px green solid;
}
.tabContent,
input {
display: none;
}
.tab1:checked ~ .tab1,
.tab2:checked ~ .tab2,
.tab3:checked ~ .tab3 {
display: block;
}
<div id="overallDiv">
<input type="radio" name="tabGroup1" id="rad1" class="tab1" checked="checked" />
<label for="rad1" class="tab">First Tab</label>
<input type="radio" name="tabGroup1" id="rad2" class="tab2" />
<label for="rad2" class="tab">Second Tab</label>
<input type="radio" name="tabGroup1" id="rad3" class="tab3" />
<label for="rad3" class="tab">Third Tab</label>
<div class="tabContent tab1" id="first">
First Tab
</div>
<div class="tabContent tab2" id="second">
Second Tab
</div>
<div class="tabContent tab3" id="third">
Third Tab
</div>
</div>
There are a couple of methods to remove whitespace. Here's a good article on a couple of methods https://davidwalsh.name/remove-whitespace-inline-block. If you don't want your html to become messy you could add a font-size of 0 to the parent element, then if you have text in the child elements add a font-size to them. Your CSS would look like this:
parent element:
#overallDiv {
font-size: 0;
}
child elements:
.tabs {
font-size: 14px;
}
Here's a jsfiddle.

Floating form elements

Essentially I'm trying to float, most of the list item elements horizontally with with the input underneath the label. Here is a template of what I'm trying to achieve.
I've included some of the code here:
<div>
<label for="headline">Headline: </label>
<input type="text" name="headline" value="Milestone" maxlength="50"size="55">
<br>
<div class="dates clearfix">
<label for="effect_date">Date of Effect:</label>
<input type="text" name="effect_date">
<label for="end_date">End Date (opt):</label>
<input type="text" name="end_date">
<label>Date Visible:</label>
<input type="radio" name="is_date_visible" value="2012">
<label for="is_date_visible_yes">Yes</label>
<input type="radio" name="is_date_visible">
<label for="is_date_visible_no">No</label>
<br>
<label>Administrative:</label>
<input type="radio" name="is_adminis" value="1">
<label for="is_admin_yes">Yes</label>
<input type="radio" name="is_adminis">
<label for="is_admin_no">No</label>
</div>
</div>​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​
And the CSS:
.clearfix:before, .clearfix:after { content: ""; display: table; }
.clearfix:after { clear: both; }
.clearfix { *zoom: 1; }
div.dates {
}
.dates label {
display: block;
color: #2c93d5;
font-size: 15px;
margin-bottom: 5px;
}
.dates input {
display: block;
}
​.dates label, .dates input {
float: left;
}
I've tried various things with the CSS all to no avail. Essentially I can't get the inputs to drop below the labels and I can't line them all up they usually come out staggered from the top.
I also have a fiddle link I've been working on:
http://jsfiddle.net/vjDEq/
Thanks for any help.
Here's something similar, without using floats:
http://jsfiddle.net/vjDEq/19/
HTML
<div>
<label for="headline">Headline: </label>
<input type="text" id="headline" name="headline" value="Milestone" maxlength="50"size="55">
</div>
<div class="dates">
<label for="effect_date">Date of Effect:
<input type="text" name="effect_date">
</label>
<label for="end_date">End Date (opt):
<input type="text" name="end_date">
</label>
<fieldset>
<legend>Date Visible:</legend>
<label for="is_date_visible_yes">
<input type="radio" name="is_date_visible" id="is_date_visible_yes" value="yes">
Yes
</label>
<label for="is_date_visible_no">
<input type="radio" name="is_date_visible" id="is_date_visible_no" value="no">
No
</label>
</fieldset>
<fieldset>
<legend>Administrative:</legend>
<label for="is_admin_yes">
<input type="radio" name="is_adminis" id="is_admin_yes" value="1">
Yes
</label>
<label for="is_admin_no">
<input type="radio" name="is_adminis" id="is_admin_no" value="0">
No
</label>
</fieldset>
</div>
​
CSS
#headline {
margin-bottom: 1em;
}
label {display: block;}
.dates label {
color: #2c93d5;
font-size: 15px;
margin-bottom: 5px;
}
.dates input {
display: block;
}
.dates fieldset input {
display: inline;
}
.dates label, .dates fieldset {
display: inline-block;
margin-right: 2em;
}
.dates fieldset label {
margin-right: 1em;
}
Instead of floats, the labels wrap the inputs and are set to inline-block. The radio buttons should be in a fieldset. Note that jsfiddle is adding normalize.css, which removes borders/margins/padding from the fieldset and legend. You have the option of floating the Administrative fieldset to the right if your layout demands it.