How to style child component html elements to parent component grid? - html

I have a component with a grid defined, I want to style a child component input elements so that they stay in a specific grid row and column; I tried doing this;
parent component html;
<div class="patient-details-grid">
<app-child-component></app-child-component>
</div>
.patient-details-grid {
gap: 15px 40px;
grid-template-columns: repeat(4, 1fr);
display: grid;
}
app-child-component {
.form {
display: block;
.firstName {
grid-area: 2 / 1 / 2 / 2;
}
.lastName,
.year,
.city,
.zipCode,
.phone,
.email {
grid-column: 1 / 3;
}
}
The form elements do not get placed into the correct grid tracks as I expected. How do I style these child elements into the parent div grid? the child component has multiple input elements like this;
<input type="text" class="firstName">
<input type="text" class="lastName">
<input type="text" class="year">
<input type="text" class="city">
<input type="text" class="zipCode">
<input type="text" class="phone">
<input type="text" class="email">

Related

How to put tooltip bullet inline with the label field

I want to put the button inline with the label and bellow them to have the full width input.
What I've made is this:
<div class="container">
<label>Tralala</label>
<input type="text" placeholder="Tralalala">
<button type="tooltip" data="This is tralalala">This is tralalala</button>
</div>
<div class="container">
<label>Tralala Tralalala Tralalala</label>
<input type="text" placeholder="Tralala Tralalala Tralalala">
<button type="tooltip" data="This is Tralala Tralalala Tralalala">This is Tralala Tralalala Tralalala</button>
</div>
So there is no posibility for me to put the button inside the label and I have to use CSS to make it.
My CSS looks like this:
.container {
display: flex;
flex-direction: column;
}
.container label { order: 0 }
.container input { order: 2 }
.container button {oder: 1 }
But from here, I don't know how to bring the label and button inline
Like this:
Change the flex-direction to row and allow wrapping.
Change the order so the inputcomes after the other elements and then make it 100% wide.
.container {
display: flex;
flex-wrap: wrap;
margin: 1em;
border: 1px solid green;
padding: 1em;
}
button {
margin-left: 1em;
}
input {
order: 2;
flex: 0 0 100%;
margin-top: 1em;
}
<div class="container">
<label>Tralala</label>
<input type="text" placeholder="Tralalala">
<button type="tooltip" data="This is tralalala">This is tralalala</button>
</div>
<div class="container">
<label>Tralala Tralalala Tralalala</label>
<input type="text" placeholder="Tralala Tralalala Tralalala">
<button type="tooltip" data="This is Tralala Tralalala Tralalala">This is Tralala Tralalala Tralalala</button>
</div>

How to create tabbed navigation for variable number of columns using ONLY CSS

I am trying to create a general solution to a problem I encounter fairly often.
I am attempting to use the checkbox hack in tandem with a CSS grid in order to create a tabbed navigation menu that doesn't need to be modified when the HTML changes. If you run the code snippet, you'll see that you can add or remove any of the input/label/section trios and the CSS can just handle it.
What I am failing to accomplish is getting the second row to span all columns effectively filling the available space. I have come to understand that I am unable to get a row to span all columns unless I define an explicit grid. Unfortunately, defining a set number of columns defeats the whole purpose of what I am trying to do.
Working under the constraint that the HTML will always be input/label/section blocks in that order, is there any way to get that second row to span all columns without defining a set number of columns? I tried to get this to work using flexbox, but I couldn't get the columns right.
I am trying to get this with just CSS please, no javascript.
#Wrapper {
display: grid;
grid-auto-columns: 1fr;
grid-template-rows: 2em calc(100% - 2em);
height: 100%;
width: 100%;
}
#Wrapper section,
input[name=buttons] {
display: none
}
/*This doesn't work*/
#Wrapper section {
grid-column-start: 1;
grid-column-end: -1;
}
#Wrapper input[name=buttons]+label {
border-style: solid;
border-width: 1px;
cursor: pointer;
grid-row-start: 1;
grid-row-end: 2;
}
#Wrapper>input[name=buttons]:checked+label {
background-color: red;
}
#Wrapper>input[name=buttons]:checked+label+section {
display: block;
width: 100%;
}
<div id='Wrapper'>
<input type='radio' id='TabButton1' name='buttons' checked></input>
<label for='TabButton1'>SECTION 1</label>
<section>
This is some content 1
</section>
<input type='radio' id='TabButton2' name='buttons'></input>
<label for='TabButton2'>SECTION 2</label>
<section>
This is some content 2
</section>
<input type='radio' id='TabButton3' name='buttons'></input>
<label for='TabButton3'>SECTION 3</label>
<section>
This is some content 3
</section>
<input type='radio' id='TabButton4' name='buttons'></input>
<label for='TabButton4'>SECTION 4</label>
<section>
This is some content 4
</section>
<input type='radio' id='TabButton5' name='buttons'></input>
<label for='TabButton5'>SECTION 5</label>
<section>
This is some content 5
</section>
</div>

Form alignment collapses into single row

I have the parent element set to newTableForm with labelColumn and mainFormColumn as children - but with the current CSS everything collapses into one row:
.newTableForm {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-rows: 30px 30px 30px 40px;
grid-gap: 10px;
grid-template-areas: "... main" "labels main" "labels main" "... main";
border: 2px dashed deeppink;
}
.labelColumn {
grid-area: labels;
}
.mainFormColumn {
grid-area: main;
}
<form method='post' action="/admin-post.php" class="newTableForm">
<h4 class="mainFormColumn">
Add a new price compare table
</h4>
<label for="store" class="labelColumn">Store</label>
<input type="text" name="store" placeholder="" class="mainFormColumn"/>
<label for="product-page" class="labelColumn">Product Page Link</label>
<input type="text" name="product-page" placeholder="Copy address here" class="mainFormColumn" />
<button class="mainFormColumn">Save new price compare table</button>
</form>
Is there a way to undo the single column stacking behavior here? I would remove the template areas altogether if not for the blank sections with ... (above and below the label section)
Again you can drop grid-template-areas as multiple grid-areas overlap - and you can use pseudo elements for this:
place labelColumn into the first column using grid-column: 1 and mainFormColumn into the second column using grid-column: 2.
after element will be the first column in the last row using grid-row: -2 and grid-column: 1
before will be first column in the first row using grid-column: 1
See demo below:
.newTableForm {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-rows: 30px 30px 30px 40px;
grid-gap: 10px;
border: 2px dashed deeppink;
}
.labelColumn {
grid-column: 1;
}
.mainFormColumn {
grid-column: 2;
}
.newTableForm:after, .newTableForm:before {
content: '';
display: block;
grid-column: 1;
}
.newTableForm:after {
grid-row: -2;
}
<form method='post' action="/admin-post.php" class="newTableForm">
<h4 class="mainFormColumn">
Add a new price compare table
</h4>
<label for="store" class="labelColumn">Store</label>
<input type="text" name="store" placeholder="" class="mainFormColumn"/>
<label for="product-page" class="labelColumn">Product Page Link</label>
<input type="text" name="product-page" placeholder="Copy address here" class="mainFormColumn" />
<button class="mainFormColumn">Save new price compare table</button>
</form>
I just update your .newTableForm css with some updates. I hope it'll help you out. Thanks
.newTableForm {
display: flex;
flex-direction: column;
border: 2px dashed deeppink;
}

Create a two-column layout of with right aligned labels and left aligned values in CSS

All,
What is the simplest way to create a simple layout that looks like this, in HTML and CSS:
Specifically - a right-aligned label on the left, and a left-aligned value on the right.
I don't want to hard-code the width of the left-column - that should be determined based on the width of the longest label.
I'm looking for an approach that's at least reasonably semantic, works well with screen-readers (e.g., screen reader should read the label, and then the value, not all the labels, then all the values), and doesn't require a whole bunch of additional <div> elements.
This seems like a reasonably common layout, so I'm assuming there's a very easy way to do it. But I've yet to figure that out myself.
A <table> would work perfectly, but as everyone reminds me, never use a <table> just for layout. And this is clearly not tabular data.
Thanks in advance!
There are a couple of options, using minimal HTML; one using CSS Grid and the other using CSS flex-box layout.
CSS Grid:
/* A simple reset to ensure that all elements and
pseudo-elements have their margin and padding
set to zero, and all are using the same box-sizing: */
*,
::before,
::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* here we set the <form> element's layout to use
grid layout: */
form {
display: grid;
/* we use the repeat() function to create 2 columns,
each column sized with a minimum of 0 width and a
maximum of 1fr; the 'fr' unit is a fractional unit
and here forces each column to take one fractional
unit of the available space to create two equal-sized
columns: */
grid-template-columns: repeat(2, minmax(0, 1fr));
/* we use the 'gap' property (formerly 'grid-gap') to
specify the gap between grid elements; here we have
0.5em above and below and 1em to the left and right: */
gap: 0.5em 1em;
width: 80vw;
margin: 0 auto;
}
label {
/* aligning the text to the right of the <label> element: */
text-align: right;
}
label::after {
/* using the 'content' property of the pseudo-element to
add the colon character: */
content: ':'
}
<form>
<!-- using the 'for' attribute to associate the label with the
relevant <input> element; the value of the 'for' attribute
must be equal to the 'id' attribute-value of the relevant
<input> -->
<label for="input1">label</label>
<input type="text" id="input1" placeholder="input 1">
<label for="input2">A longer label</label>
<input type="text" id="input2" placeholder="input 2">
<label for="input3">Another slightly longer label</label>
<input type="text" id="input3" placeholder="input 3">
<label for="input4">A label that goes on, frankly, for quite a bit further than might be common for the average <label> element</label>
<input type="text" id="input4" placeholder="input 4">
</form>
JS Fiddle demo.
Flexbox:
/* A simple reset to ensure that all elements and
pseudo-elements have their margin and padding
set to zero, and all are using the same box-sizing: */
*,
::before,
::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* setting the layout of the <form> to flexbox: */
form {
display: flex;
/* allowing the child elements of the <form> to wrap
to new lines when necessary: */
flex-wrap: wrap;
width: 80vw;
margin: 0 auto;
}
/* Setting common properties for the <label> and <input>
elements: */
label,
input {
/* assigning the flex-grow and flex-shrink (respectively)
properties to 1, in order that they grow/shrink by the
same amount relative to each other; and setting the
flex-basis to 40% (the percentage derived from the parent)
in order to assign a width that's too large to accommodate
more than two elements per line: */
flex: 1 1 40%;
/* setting the margin above/below each 'row' to be 0.5em,
and 0 to the left and right: */
margin: 0.5em 0;
}
label {
text-align: right;
/* setting the margin-right of the <label> to 1em to enforce a
gutter between the <label> and the neighbouring <input> (the
CSS Box Alignment module (level 3) introduces the 'gap' property
that can also be used in the flexbox layout (among others) but
that's not yet supported by browsers, so we have to use margins: */
margin-right: 1em;
}
label::after {
content: ':'
}
<form>
<label for="input1">label</label>
<input type="text" id="input1" placeholder="input 1">
<label for="input2">A longer label</label>
<input type="text" id="input2" placeholder="input 2">
<label for="input3">Another slightly longer label</label>
<input type="text" id="input3" placeholder="input 3">
<label for="input4">A label that goes on, frankly, for quite a bit further than might be common for the average <label> element</label>
<input type="text" id="input4" placeholder="input 4">
</form>
JS Fiddle demo.
Now, with both of the above approaches there is one requirement that may not be appropriate for your use-case: the <label> element must implement a for attribute, which requires that the associated <input> must also have an id attribute (and those values must be equivalent).
To avoid that, we could instead nest the <input> within the <label>, which automatically associates the <label> and <input>; this would give (potentially) cleaner HTML:
Grid, again:
*,
::before,
::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
form {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.5em 1em;
width: 80vw;
margin: 0 auto;
}
label {
/* it's a crude simplification, but effectively we remove
the <label> from the DOM and instead show its contents;
the text portion, and the <input>, become independant
grid-items (sort of): */
display: contents;
}
<form>
<label>label
<input type="text" placeholder="input 1"></label>
<label>A longer label
<input type="text" placeholder="input 2"></label>
<label>Another slightly longer label
<input type="text" placeholder="input 3"></label>
<label>A label that goes on, frankly, for quite a bit further than might be common for the average label element
<input type="text" placeholder="input 4"></label>
</form>
JS Fiddle demo.
In the above snippet you may notice that:
we no longer use label::after to insert the presentational ':' characters, since that would – obviously – be placed after the <label> content, following the <input> and would create another grid-item (demo), and
the <label> text is no longer right-aligned; this is because text-align doesn't seem to work on the text.
*,
::before,
::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
form {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.5em 1em;
width: 80vw;
margin: 0 auto;
}
label {
display: contents;
text-align: right;
}
<form>
<label>label
<input type="text" placeholder="input 1"></label>
<label>A longer label
<input type="text" placeholder="input 2"></label>
<label>Another slightly longer label
<input type="text" placeholder="input 3"></label>
<label>A label that goes on, frankly, for quite a bit further than might be common for the average label element
<input type="text" placeholder="input 4"></label>
</form>
JS Fiddle demo.
We could improve things, visually, be wrapping the text-content of the <label> in an element, such as a <span> to restore that presentation:
*,
::before,
::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
form {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.5em 1em;
width: 80vw;
margin: 0 auto;
}
label {
display: contents;
text-align: right;
}
label span::after {
content: ':';
}
<form>
<label><span>label</span>
<input type="text" placeholder="input 1"></label>
<label><span>A longer label</span>
<input type="text" placeholder="input 2"></label>
<label><span>Another slightly longer label</span>
<input type="text" placeholder="input 3"></label>
<label><span>A label that goes on, frankly, for quite a bit further than might be common for the average label element</span>
<input type="text" placeholder="input 4"></label>
</form>
It's also worth noting that both CSS Grid and CSS Flexbox allow us to reorder elements visually in the browser differently than they appear in the DOM; this can allow us to style the <label> elements based on the state of the associated <input>, for example,
Grid:
*,
::before,
::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
form {
display: grid;
/* to ensure that the layout backfills the empty spaces
created by moving content around: */
grid-auto-flow: dense;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.5em 1em;
width: 80vw;
margin: 0 auto;
}
label {
display: contents;
text-align: right;
}
input {
/* positioning the <input> elements in the secpond
grid-track/column: */
grid-column: 2;
}
label span {
/* positioning the <span> elements in the first
grid-track/column: */
grid-column: 1;
}
label span::after {
content: ':';
}
input:placeholder-shown+span {
color: rebeccapurple;
}
input:not(:placeholder-shown)+span {
color: limegreen;
font-weight: bold;
}
input:focus+span,
input:active+span {
color: #f90;
}
<form>
<label>
<input type="text" placeholder="input 1">
<span>label</span>
</label>
<label>
<input type="text" placeholder="input 2">
<span>A longer label</span>
</label>
<label>
<input type="text" placeholder="input 3">
<span>Another slightly longer label</span>
</label>
<label>
<input type="text" placeholder="input 4">
<span>A label that goes on, frankly, for quite a bit further than might be common for the average label element</span>
</label>
</form>
JS Fiddle demo.
Flexbox:
*,
::before,
::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
form {
width: 80vw;
margin: 0 auto;
}
label {
display: flex;
margin: 0.5em 0;
}
label span,
label input {
flex: 1 1 50%;
}
label span {
order: 1;
text-align: right;
margin-right: 1em;
}
label input {
order: 2;
}
label span::after {
content: ':';
}
label span::after {
content: ':';
}
input:placeholder-shown+span {
color: rebeccapurple;
}
input:not(:placeholder-shown)+span {
color: limegreen;
font-weight: bold;
}
input:focus+span,
input:active+span {
color: #f90;
}
<form>
<label>
<input type="text" placeholder="input 1">
<span>label</span>
</label>
<label>
<input type="text" placeholder="input 2">
<span>A longer label</span>
</label>
<label>
<input type="text" placeholder="input 3">
<span>Another slightly longer label</span>
</label>
<label>
<input type="text" placeholder="input 4">
<span>A label that goes on, frankly, for quite a bit further than might be common for the average label element</span>
</label>
</form>
JS Fiddle demo.
It's worth noting, though, that grid-auto-flow: dense, as well as rearranging the visual presentation of elements, can cause problems for those users of the web using screen readers or keyboard interaction. So, while it enables some prettiness, it's worth considering if that prettiness comes at the cost of usability (and potential legally-required accessibility).
Further, in the latter examples, the use of a nested <span> element to allow for styling of the text-content of the <label> element (whether for alignment reasons, adding the ':' characters or styling in response to interaction with the <input> elements, this may be unnecessary complication of a potentially 'clean' HTML markup.
References:
Selectors:
:active.
::after.
:focus.
:not().
:placeholder-shown.
Properties
box-sizing.
display.
flex.
flex-basis.
flex-grow.
flex-shrink.
gap.
grid-auto-flow.
grid-column.
grid-template-columns.
minmax().
order.
repeat().
Property-values:
<length> (units).
Bibliography:
"A Complete Guide to Grid."
"A Complete Guide to Flexbox."
"Basic Concepts of Flexbox."
"Basic Concepts of Grid Layout."
CSS tables to the rescue : https://css-tricks.com/almanac/properties/d/display/
These aren't tables, but can be used to recreate table behavior.
.notATable {
display:table;
list-style:none;
padding-left:0;
}
.notATable > li
{
display:table-row;
}
.notATable > li > *
{
display:table-cell;
padding:5px;
}
.notATable label {
font-weight:bold;
text-align:right;
}
.notATable label:after {
content: ':';
}
<ul class="notATable">
<li><label>Label</label><div>Value</div></li>
<li><label>Another Label</label><div>Some Value</div></li>
<li><label>A longer Label</label><div>Another Value</div></li>
<li><label>Short Label</label><div>A different Value</div></li>
<li><label>Really, Really Long Label</label><div>Last Value</div></li>
</ul>
Now you can use CSS to change the layout of your markup, for example you could use media-queries to display your labels and values differently on mobile devices.
Is this simple?
*{
padding: 5px;
margin: 0;
font-family: verdana;
}
.d-table {
display:table;
}
.m-auto{
margin:auto
}
.d-flex{
display:flex;
}
.d-flex > div{
height: auto;
display: flex;
flex-direction: column;
justify-content: space-around;
}
label{
display:block;
text-align:right;
font-weight: bold;
margin-right: 5px;
}
<div class="d-table m-auto">
<div class="d-flex">
<div>
<label>Label:</label>
<label>Another label:</label>
<label>A long label:</label>
<label>Short label:</label>
<label>Really, really long label:</label>
</div>
<div>
<p>Value</p>
<p>Some value</p>
<p>Another value</p>
<p>A different value</p>
<p>Last value</p>
</div>
</div>
</div>

Vertically align inputs with each other

I have two inputs, but the pre-displayed labels have different length, causing the inputs not to start from the same position (vertically speaking). How to achieve that?
Some of my attempts are:
input {
margin-left: 50px;
}
input {
vertical-align:middle;
}
Please notice that display: block; will make the label and input lose their initial corresponding positions!
My JSFiddle.
You can make use of CSS table layout. The parent element acts as a table row and the child elements as table cells.
.input-container {
display: table-row;
}
.input-container * {
display: table-cell;
margin-left: 5px;
}
<fieldset>
<legend>Team1</legend>
<div class="input-container">
<label for="player1">Player1</label>
<input type="number" name="player1">
</div>
<div class="input-container">
<label for="player2">Player2345</label>
<input type="number" name="player2">
</div>
</fieldset>