Reputation: 2629
I would like to do something similar to justify-content:space-around
or justify-content:space-between
, but with :
It would be simple by wrap elements but I can't because these items (.left
, .middle
, .right
) would be checkboxes influencing the styles of elements below (and there is no well-supported parent selector).
I found this answer to emulate first-of-class
for the right side, but didn't find something similar to emulate last-of-class
.
/* emulate first-of-class */
.container>.right {
margin-left: auto;
}
.container>.right~.right {
margin-left: unset;
}
Here is a snippet of my current attempt :
.container {
display: flex;
flex-wrap: wrap;
}
input {
display: none;
}
label {
padding: 0 10px;
background-color: orange;
}
.container>.right {
margin-left: auto;
}
.container>.right~.right {
margin-left: unset;
}
#check-center {
width: 100%;
text-align: center;
}
[ lang ] {
display: none;
}
[ name="language" ]:checked+label {
background-color: pink;
}
[ value="en" ]:checked ~ [ lang="en" ],
[ value="en" ]:checked ~* [ lang="en" ],
[ value="fr" ]:checked ~ [ lang="fr" ],
[ value="fr" ]:checked ~* [ lang="fr" ],
[ value="es" ]:checked ~ [ lang="es" ],
[ value="es" ]:checked ~* [ lang="es" ] {
display: block;
}
/*for codepen*/
html[ lang ] {
display: block;
}
<div class="container">
<input type="radio" name="left-field" id="A" />
<label class="left" for="A">A</label>
<input type="radio" name="left-field" id="B" />
<label class="left" for="B">B</label>
<input type="radio" name="middle-field" id="C" />
<label class="middle" for="C">C</label>
<input type="radio" name="middle-field" id="D" />
<label class="middle" for="D">D</label>
<input type="radio" name="middle-field" id="E" />
<label class="middle" for="E">E</label>
<input type="radio" name="language" id="enLang" value="en" />
<label class="right" for="enLang">en</label>
<input type="radio" name="language" id="frLang" value="fr" />
<label class="right" for="frLang">fr</label>
<input type="radio" name="language" id="esLang" value="es" />
<label class="right" for="esLang">es</label>
<div id="check-center">|</div>
<div lang="en">EN selected</div>
<div lang="fr">FR selected</div>
<div lang="es">ES selected</div>
<div>
<div lang="en">EN selected</div>
<div lang="fr">FR selected</div>
<div lang="es">ES selected</div>
</div>
</div>
I could cheat by adding a specific class to the last left element to apply margin-right:auto;
and the first right element to apply margin-left:auto;
in a display:flex
container but it's not the best and even then, the middle items wouldn't be centered if the left and right parts have not the same width.
.container {
display: flex;
flex-wrap: wrap;
}
input {
display: none;
}
label {
padding: 0 10px;
background-color: orange;
}
.cheat.left {
margin-right: auto;
}
.cheat.right {
margin-left: auto;
}
#check-center {
width: 100%;
text-align: center;
}
[ lang ] {
display: none;
}
[ name="language" ]:checked+label {
background-color: pink;
}
[ value="en" ]:checked ~ [ lang="en" ],
[ value="en" ]:checked ~* [ lang="en" ],
[ value="fr" ]:checked ~ [ lang="fr" ],
[ value="fr" ]:checked ~* [ lang="fr" ],
[ value="es" ]:checked ~ [ lang="es" ],
[ value="es" ]:checked ~* [ lang="es" ] {
display: block;
}
/*for codepen*/
html[ lang ] {
display: block;
}
<div class="container">
<input type="radio" name="left-field" id="A" />
<label class="left" for="A">A</label>
<input type="radio" name="left-field" id="B" />
<label class="cheat left" for="B">B</label>
<input type="radio" name="middle-field" id="C" />
<label class="middle" for="C">C</label>
<input type="radio" name="middle-field" id="D" />
<label class="middle" for="D">D</label>
<input type="radio" name="middle-field" id="E" />
<label class="middle" for="E">E</label>
<input type="radio" name="language" id="enLang" value="en" />
<label class="cheat right" for="enLang">en</label>
<input type="radio" name="language" id="frLang" value="fr" />
<label class="right" for="frLang">fr</label>
<input type="radio" name="language" id="esLang" value="es" />
<label class="right" for="esLang">es</label>
<div id="check-center">|</div>
<div lang="en">EN selected</div>
<div lang="fr">FR selected</div>
<div lang="es">ES selected</div>
<div>
<div lang="en">EN selected</div>
<div lang="fr">FR selected</div>
<div lang="es">ES selected</div>
</div>
</div>
My current goal is to display elements depending on the selected language even if JavaScript is disabled, so I'm looking for a solution without JavaScript.
As HackerFrosch suggested, I tried to solve it by using a grid but I'm not used to it, the .middle
items are not centered and I did not manage to make the elements below .right
divs 100% width as by default.
.container {
display: grid;
grid-template-columns: auto 1fr auto auto auto 1fr auto auto;
}
input {
display: none;
}
label {
padding: 0 10px;
background-color: orange;
width: fit-content;
}
.cheat.left {
margin-right: auto;
}
.cheat.right {
margin-left: auto;
}
#check-center {
width: 100%;
text-align: center;
}
[ lang] {
display: none;
}
[ name="language"]:checked+label {
background-color: pink;
}
[ value="en"]:checked~[ lang="en"],
[ value="en"]:checked~* [ lang="en"],
[ value="fr"]:checked~[ lang="fr"],
[ value="fr"]:checked~* [ lang="fr"],
[ value="es"]:checked~[ lang="es"],
[ value="es"]:checked~* [ lang="es"] {
display: block;
}
/*for codepen*/
html[ lang] {
display: block;
}
<div class="container">
<input type="radio" name="left-field" id="A" />
<label class="left" for="A">A</label>
<input type="radio" name="left-field" id="B" />
<label class="cheat left" for="B">B</label>
<input type="radio" name="middle-field" id="C" />
<label class="middle" for="C">C</label>
<input type="radio" name="middle-field" id="D" />
<label class="middle" for="D">D</label>
<input type="radio" name="middle-field" id="E" />
<label class="middle" for="E">E</label>
<input type="radio" name="language" id="enLang" value="en" />
<label class="cheat right" for="enLang">en</label>
<input type="radio" name="language" id="frLang" value="fr" />
<label class="right" for="frLang">fr</label>
<input type="radio" name="language" id="esLang" value="es" />
<label class="right" for="esLang">es</label>
<div lang="en">EN selected</div>
<div lang="fr">FR selected</div>
<div lang="es">ES selected</div>
<div>
<div lang="en">EN selected</div>
<div lang="fr">FR selected</div>
<div lang="es">ES selected</div>
</div>
</div>
<div id="check-center">|</div>
Is there a way to achieve this?
Upvotes: 8
Views: 368
Reputation: 378
This does well to maintain the center while still allowing css selectors. It will maintain center adding more elements to the left, middle, or right containers. The middle container can have odd or even elements and it will still maintain center, provided there is adequate room.
The limitations of this approach is that your header height must be fixed, and the absolutely positioned #dynamic_children div top property must reflect that value. Also, due to IE 11's poor flex implementation, this will not work properly and obviously they will never fix that since IE 11 is no longer supported. I am unsure if that matters for you.
body {
padding: 0;
margin: 0;
}
.container {
display: flex;
flex-wrap: nowrap;
height: 30px;
max-height: 30px;
}
#left_container {
display: flex;
justify-content: left;
flex: 1;
flex-wrap: nowrap;
align-items: center;
}
#middle_container {
display: flex;
justify-content: center;
flex: 0;
flex-wrap: nowrap;
align-items: center;
}
#right_container {
display: flex;
justify-content: right;
flex: 1;
flex-wrap: wrap;
align-items: center;
margin-left: auto;
}
#check-center {
display: block;
width: 100%;
height: 20px;
text-align: center;
background-color: rgb(255, 255, 0);
}
#dynamic_children {
width: 100%;
display: block;
position: absolute;
top: 30px;
left: 0;
}
input {
display: none;
}
label {
padding: 0 10px;
background-color: orange;
}
[ lang] {
display: none;
}
[ name="language"]:checked+label {
background-color: pink;
}
[ value="en"]:checked~[ lang="en"],
[ value="en"]:checked~* [ lang="en"],
[ value="fr"]:checked~[ lang="fr"],
[ value="fr"]:checked~* [ lang="fr"],
[ value="es"]:checked~[ lang="es"],
[ value="es"]:checked~* [ lang="es"] {
display: block;
}
<body>
<div class="container">
<div id="left_container">
<input type="radio" name="left-field" id="A" />
<label class="left" for="A">A</label>
<input type="radio" name="left-field" id="B" />
<label class="left" for="B">B</label>
</div>
<div id="middle_container">
<input type="radio" name="middle-field" id="C" />
<label class="middle" for="C">C</label>
<input type="radio" name="middle-field" id="D" />
<label class="middle" for="D">D</label>
<input type="radio" name="middle-field" id="E" />
<label class="middle" for="E">E</label>
</div>
<div id="right_container">
<input type="radio" name="language" id="enLang" value="en" />
<label class="right" for="enLang">en</label>
<input type="radio" name="language" id="frLang" value="fr" />
<label class="right" for="frLang">fr</label>
<input type="radio" name="language" id="esLang" value="es" />
<label class="right" for="esLang">es</label>
<div id="dynamic_children">
<div id="check-center">-|-</div>
<div>
<div lang="en">EN selected div 1</div>
<div lang="fr">FR selected div 1</div>
<div lang="es">ES selected div 1</div>
<div lang="en">EN selected div 2</div>
<div lang="fr">FR selected div 2</div>
<div lang="es">ES selected div 2</div>
<div lang="en">EN selected div 3</div>
<div lang="fr">FR selected div 3</div>
<div lang="es">ES selected div 3</div>
</div>
</div>
</div>
</div>
</body>
Upvotes: 0
Reputation: 4936
Something like this - using left margin auto on the first center and right classes:
/* flex container */
.container { display: flex; }
/* left margin auto on all center/right classes */
.center, .right { margin-left: auto; }
/* remove auto margin on non firsts */
.center~.center, .right~.right { margin-left: initial; }
/* just a bit of styling */
div { padding: .5rem; }
.left { background: tomato; }
.center { background: orange; }
.right { background: yellowgreen; }
<div class="container">
<div class="left">Left 1</div>
<div class="left">Left 2</div>
<div class="left">Left 3</div>
<div class="center">Center 1</div>
<div class="center">Center 2</div>
<div class="center">Center 3</div>
<div class="right">Right 1</div>
<div class="right">Right 2</div>
<div class="right">Right 3</div>
</div>
Upvotes: 0
Reputation: 211
As per your requirements, you need to use grid
property.
<!DOCTYPE html>
<html>
<style>
.container {
display: grid;
grid-template-columns: 50px auto 50px 50px auto 50px 50px 50px;
}
input {
display: none;
}
label {
padding: 0 10px;
background-color: orange;
width: 12px;
}
#check-center {
width: 100%;
text-align: center;
}
[ lang ] {
display: none;
}
[ name="language" ]:checked+label {
background-color: pink;
}
</style>
<body>
<div class="container">
<input type="radio" name="left-field" id="A" />
<label class="left" for="A">A</label>
<input type="radio" name="left-field" id="B" />
<label class="left" for="B">B</label>
<input type="radio" name="middle-field" id="C" />
<label class="middle" for="C">C</label>
<input type="radio" name="middle-field" id="D" />
<label class="middle" for="D">D</label>
<input type="radio" name="middle-field" id="E" />
<label class="middle" for="E">E</label>
<input type="radio" name="language" id="enLang" value="en" />
<label class="right" for="enLang">en</label>
<input type="radio" name="language" id="frLang" value="fr" />
<label class="right" for="frLang">fr</label>
<input type="radio" name="language" id="esLang" value="es" />
<label class="right" for="esLang">es</label>
<div lang="en">EN selected</div>
<div lang="fr">FR selected</div>
<div lang="es">ES selected</div>
<div>
<div lang="en">EN selected</div>
<div lang="fr">FR selected</div>
<div lang="es">ES selected</div>
</div>
</div>
</body>
</html>
Upvotes: -1
Reputation: 8538
You can try to solve this with flex and use the calc() function to manage the left or right margins. So, I created four classes to use one of them to center the middle classes.
/* adjust for left side, put to the first middle label */
.one-left.middle {
margin-inline-start: calc((4 * var(--block-width) / 2));
}
.two-left.middle {
margin-inline-start: calc((3 * var(--block-width) / 3));
}
/* adjust for right side, set to the last meddle label */
.one-right.middle {
margin-inline-end: calc((4 * var(--block-width) / 2));
}
.two-right.middle {
margin-inline-end: calc((3 * var(--block-width) / 3));
}
*,
::after,
::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
--block-width: 50px;
display: flex;
justify-content: center;
}
.gap.left {
margin-inline-end: auto;
}
.gap.right {
margin-inline-start: auto;
}
/* adjust for left side, put to the first middle label */
.one-left.middle {
margin-inline-start: calc((4 * var(--block-width) / 2));
}
.two-left.middle {
margin-inline-start: calc((3 * var(--block-width) / 3));
}
/* adjust for right side, set to the last meddle label */
.one-right.middle {
margin-inline-end: calc((4 * var(--block-width) / 2));
}
.two-right.middle {
margin-inline-end: calc((3 * var(--block-width) / 3));
}
input {
display: none;
}
label {
padding: 0 10px;
background-color: orange;
width: var(--block-width);
}
#check-center {
width: 100%;
text-align: center;
}
[lang] {
display: none;
}
[name='language']:checked+label {
background-color: pink;
}
[value='en']:checked~[lang='en'],
[value='en']:checked~* [lang='en'],
[value='fr']:checked~[lang='fr'],
[value='fr']:checked~* [lang='fr'],
[value='es']:checked~[lang='es'],
[value='es']:checked~* [lang='es'] {
display: block;
}
<div class="container">
<input type="radio" name="left-field" id="A" />
<label class="left" for="A">A</label>
<!-- <input type="radio" name="left-field" id="A1" />
<label class="left" for="A1">A1</label> -->
<input type="radio" name="left-field" id="B" />
<label class="gap left" for="B">B</label>
<input type="radio" name="middle-field" id="C" />
<label class="two-left middle" for="C">C</label>
<input type="radio" name="middle-field" id="D" />
<label class="middle" for="D">D</label>
<input type="radio" name="middle-field" id="E" />
<label class="middle" for="E">E</label>
<input type="radio" name="language" id="enLang" value="en" />
<label class="gap right" for="enLang">en</label>
<input type="radio" name="language" id="frLang" value="fr" />
<label class="right" for="frLang">fr</label>
<input type="radio" name="language" id="esLang" value="es" />
<label class="right" for="esLang">es</label>
<div lang="en">EN selected</div>
<div lang="fr">FR selected</div>
<div lang="es">ES selected</div>
<div>
<div lang="en">EN selected</div>
<div lang="fr">FR selected</div>
<div lang="es">ES selected</div>
</div>
</div>
<div id="check-center">|</div>
*,
::after,
::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
--block-width: 50px;
display: flex;
justify-content: center;
}
.gap.left {
margin-inline-end: auto;
}
.gap.right {
margin-inline-start: auto;
}
/* adjust for left side, put to the first middle label */
.one-left.middle {
margin-inline-start: calc((4 * var(--block-width) / 2));
}
.two-left.middle {
margin-inline-start: calc((3 * var(--block-width) / 3));
}
/* adjust for right side, set to the last meddle label */
.one-right.middle {
margin-inline-end: calc((4 * var(--block-width) / 2));
}
.two-right.middle {
margin-inline-end: calc((3 * var(--block-width) / 3));
}
input {
display: none;
}
label {
padding: 0 10px;
background-color: orange;
width: var(--block-width);
}
#check-center {
width: 100%;
text-align: center;
}
[lang] {
display: none;
}
[name='language']:checked+label {
background-color: pink;
}
[value='en']:checked~[lang='en'],
[value='en']:checked~* [lang='en'],
[value='fr']:checked~[lang='fr'],
[value='fr']:checked~* [lang='fr'],
[value='es']:checked~[lang='es'],
[value='es']:checked~* [lang='es'] {
display: block;
}
<div class="container">
<input type="radio" name="left-field" id="A" />
<label class="left" for="A">A</label>
<input type="radio" name="left-field" id="A1" />
<label class="left" for="A1">A1</label>
<input type="radio" name="left-field" id="B" />
<label class="gap left" for="B">B</label>
<input type="radio" name="middle-field" id="C" />
<label class="middle" for="C">C</label>
<input type="radio" name="middle-field" id="D" />
<label class="middle" for="D">D</label>
<input type="radio" name="middle-field" id="E" />
<label class="one-right middle" for="E">E</label>
<input type="radio" name="language" id="enLang" value="en" />
<label class="gap right" for="enLang">en</label>
<!--<input type="radio" name="language" id="frLang" value="fr" />
<label class="right" for="frLang">fr</label>
<input type="radio" name="language" id="esLang" value="es" />
<label class="right" for="esLang">es</label> -->
<div lang="en">EN selected</div>
<div lang="fr">FR selected</div>
<div lang="es">ES selected</div>
<div>
<div lang="en">EN selected</div>
<div lang="fr">FR selected</div>
<div lang="es">ES selected</div>
</div>
</div>
<div id="check-center">|</div>
Upvotes: 1
Reputation: 364
A solution to your problem is the css grid layout
. You can customize the positioning in this example if you want. I hope that helps.
.container {
display: grid;
grid-template-columns: 50px auto 50px 50px auto 50px 50px 50px;
}
input {
display: none;
}
label {
padding: 0 10px;
background-color: orange;
width: 20px;
}
#check-center {
width: 100%;
text-align: center;
}
[ lang ] {
display: none;
}
[ name="language" ]:checked+label {
background-color: pink;
}
[ value="en" ]:checked ~ [ lang="en" ],
[ value="en" ]:checked ~* [ lang="en" ],
[ value="fr" ]:checked ~ [ lang="fr" ],
[ value="fr" ]:checked ~* [ lang="fr" ],
[ value="es" ]:checked ~ [ lang="es" ],
[ value="es" ]:checked ~* [ lang="es" ] {
display: block;
}
/*for codepen*/
html[ lang ] {
display: block;
}
<div class="container">
<input type="radio" name="left-field" id="A" />
<label class="left" for="A">A</label>
<input type="radio" name="left-field" id="B" />
<label class="left" for="B">B</label>
<input type="radio" name="middle-field" id="C" />
<label class="middle" for="C">C</label>
<input type="radio" name="middle-field" id="D" />
<label class="middle" for="D">D</label>
<input type="radio" name="middle-field" id="E" />
<label class="middle" for="E">E</label>
<input type="radio" name="language" id="enLang" value="en" />
<label class="right" for="enLang">en</label>
<input type="radio" name="language" id="frLang" value="fr" />
<label class="right" for="frLang">fr</label>
<input type="radio" name="language" id="esLang" value="es" />
<label class="right" for="esLang">es</label>
<div id="check-center">|</div>
<div lang="en">EN selected</div>
<div lang="fr">FR selected</div>
<div lang="es">ES selected</div>
<div>
<div lang="en">EN selected</div>
<div lang="fr">FR selected</div>
<div lang="es">ES selected</div>
</div>
</div>
Upvotes: 3