Make parent element “resize” to equal the width of the biggest of the children (responsive switch-toggle)

余生颓废 提交于 2021-02-19 07:36:41

问题


I've come up with the following solution for the toggle switch:

.cookiemanagement__switchWrapper {
  display: flex;
  align-items: center;
}
.cookiemanagement__switchWrapper:last-of-type {
  margin-top: 15px;
}
.cookiemanagement__switch {
  display: inline-block;
  position: relative;
}
.cookiemanagement__switchInput {
  cursor: pointer;
  height: 100%;
  opacity: 0;
  position: absolute;
  width: 100%;
  z-index: 1;
}
.cookiemanagement__switchToggle {
  align-items: center;
  background-color: #9a3d37;
  border-radius: 50px;
  display: flex;
  height: 24px;
  justify-content: space-between;
  position: relative;
  transition: background-color ease-out 0.3s;
  z-index: 0;
}
.cookiemanagement__switchToggle:before {
  background: #fff;
  box-shadow: 1px 0 2px #646464;
  border-radius: 50%;
  border: 1px solid #aaaaaa;
  content: "";
  display: block;
  height: 24px;
  left: 0;
  position: absolute;
  top: 0;
  transition: 0.2s ease-out;
  width: 24px;
  z-index: 2;
}
.cookiemanagement__switchToggleValue {
  text-transform: uppercase;
  line-height: normal;
  transition: opacity 0.2s ease-out 0.1s;
}
.cookiemanagement__switchToggleValue--on {
  margin: 0 4px 0 8px;
  opacity: 0;
}
.cookiemanagement__switchToggleValue--off {
  margin: 0 8px 0 4px;
  opacity: 1;
}
.cookiemanagement__switchInput:checked ~ .cookiemanagement__switchToggle {
  background-color: #6a7d39;
}
.cookiemanagement__switchInput:checked ~ .cookiemanagement__switchToggle:before {
  left: calc(100% - 24px);
  box-shadow: -1px 0 2px #646464;
}
.cookiemanagement__switchInput:checked ~ .cookiemanagement__switchToggle .cookiemanagement__switchToggleValue--on {
  opacity: 1;
}
.cookiemanagement__switchInput:checked ~ .cookiemanagement__switchToggle .cookiemanagement__switchToggleValue--off {
  opacity: 0;
}
.cookiemanagement__switchLabel {
  margin-left: 15px;
}
<div class="cookiemanagement__switch">
    <input class="cookiemanagement__switchInput" id="id1140334900" role="switch" type="checkbox" value="3" name="analytics3">
    <div class="cookiemanagement__switchToggle">
        <span class="cookiemanagement__switchToggleValue cookiemanagement__switchToggleValue--on">yes</span>
        <span class="cookiemanagement__switchToggleValue cookiemanagement__switchToggleValue--off">no</span>
    </div>
</div>



<div class="cookiemanagement__switch">
    <input class="cookiemanagement__switchInput" id="id1140334900" role="switch" type="checkbox" value="3" name="analytics3">
    <div class="cookiemanagement__switchToggle">
        <span class="cookiemanagement__switchToggleValue cookiemanagement__switchToggleValue--on">diakh</span>
        <span class="cookiemanagement__switchToggleValue cookiemanagement__switchToggleValue--off">ara</span>
    </div>
</div>

However, I have some issues with supporting the internationalization of the values. Since right now the width of the whole element is generated from the width of two children which is "YES" and not "NO" text.

But if longer values are used like "DIAKH" and "ARA" (Georgian) the element looks very wide.

So I am investigating the way to make the whole component width to equal:
width of the biggest children (text length) + 8px + 26px

8px - margin between circle and text (red rectangle part)
26px - width/height of the circle (orange rectangle part)

Below is the illustration of what is being intended to describe, where DIAKH text represents the biggest child.


回答1:


One of the possible solutions is using a negative margin-top to put yes and no one behind another, while keeping them both in the flow so the bigger one would give its width to the parent:

p * {
  box-sizing: border-box;
  margin: 0;
  padding: 0
}

label {
  position: relative;
  display: inline-block;
  margin: 0 0 0 .5em;
  color: #fff;
}

input {
  display: none
}

.key {
  position: absolute;
  z-index: 1;
  top: -.2em;
  left: -.05em;
  width: 2em;
  height: 2em;
  border: solid 1px rgba(0, 0, 0, .3);
  border-radius: 55%;
  box-shadow: .1em .1em .1em -.05em rgba(0, 0, 0, .5);
  background: ivory;
  transition: .3s;
}

.yes,
.no {
  display: block;
  margin: 0;
  border-radius: .8em;
  line-height: 1.6;
  box-shadow: inset .1em .1em .1em -.05em rgba(0, 0, 0, .3);
  transition: opacity .3s;
}

.yes {
  padding: 0 2.5em 0 .5em;
  background: forestgreen;
  opacity: 0;
}

.no {
  margin-top: -1.6em;
  padding: 0 .5em 0 2.5em;
  text-align: right;
  background: firebrick;
  opacity: 1;
}

:checked~.key {
  left: calc(100% - 2em);
}

:checked~.yes {
  opacity: 1
}

:checked~.no {
  opacity: 0
}
<p>English:
  <label>
    <input type="checkbox" checked>
    <span class="key"></span>
    <span class="yes">YES</span>
    <span class="no">NO</span>
  </label>
</p>

<p>Georgian:
  <label>
    <input type="checkbox">
    <span class="key"></span>
    <span class="yes">DIAKH</span>
    <span class="no">ARA</span>
  </label>
</p>

<p>Scots Gaelic:
  <label>
    <input type="checkbox" checked>
    <span class="key"></span>
    <span class="yes">THA</span>
    <span class="no">CHAN EIL</span>
  </label>
</p>



回答2:


You can achieve that using flexbox on the parent of this switchs and the width: fit-content property:

ul {
  display: flex;
  flex-direction: column;
  width: fit-content;
}

.cookiemanagement__switchWrapper {
  display: flex;
  align-items: center;
  width: 100%;
}

.cookiemanagement__switchWrapper:last-of-type {
  margin-top: 15px;
}

.cookiemanagement__switch {
  display: inline-block;
  position: relative;
  width: 100%;

}

.cookiemanagement__switchInput {
  cursor: pointer;
  height: 100%;
  opacity: 0;
  position: absolute;
  width: 100%;
  z-index: 1;
}

.cookiemanagement__switchToggle {
  align-items: center;
  background-color: #9a3d37;
  border-radius: 50px;
  display: flex;
  height: 24px;
  justify-content: space-between;
  position: relative;
  transition: background-color ease-out 0.3s;
  z-index: 0;
}

.cookiemanagement__switchToggle:before {
  background: #fff;
  box-shadow: 1px 0 2px #646464;
  border-radius: 50%;
  border: 1px solid #aaaaaa;
  content: "";
  display: block;
  height: 24px;
  left: 0;
  position: absolute;
  top: 0;
  transition: 0.2s ease-out;
  width: 24px;
  z-index: 2;
}

.cookiemanagement__switchToggleValue {
  text-transform: uppercase;
  line-height: normal;
  transition: opacity 0.2s ease-out 0.1s;
}

.cookiemanagement__switchToggleValue--on {
  margin: 0 4px 0 8px;
  opacity: 0;
}

.cookiemanagement__switchToggleValue--off {
  margin: 0 8px 0 4px;
  opacity: 1;
}

.cookiemanagement__switchInput:checked~.cookiemanagement__switchToggle {
  background-color: #6a7d39;
}

.cookiemanagement__switchInput:checked~.cookiemanagement__switchToggle:before {
  left: calc(100% - 24px);
  box-shadow: -1px 0 2px #646464;
}

.cookiemanagement__switchInput:checked~.cookiemanagement__switchToggle .cookiemanagement__switchToggleValue--on {
  opacity: 1;
}

.cookiemanagement__switchInput:checked~.cookiemanagement__switchToggle .cookiemanagement__switchToggleValue--off {
  opacity: 0;
}

.cookiemanagement__switchLabel {
  margin-left: 15px;
}
<ul>
  <li class="cookiemanagement__switchWrapper">
    <div class="cookiemanagement__switch">
      <input class="cookiemanagement__switchInput" id="id1140334900" role="switch" type="checkbox" value="3" name="analytics3">
      <div class="cookiemanagement__switchToggle">
        <span class="cookiemanagement__switchToggleValue cookiemanagement__switchToggleValue--on">yes</span>
        <span class="cookiemanagement__switchToggleValue cookiemanagement__switchToggleValue--off">no</span>
      </div>
    </div>
  </li>

  <li class="cookiemanagement__switchWrapper">
    <div class="cookiemanagement__switch">
      <input class="cookiemanagement__switchInput" id="id1140334900" role="switch" type="checkbox" value="3" name="analytics3">
      <div class="cookiemanagement__switchToggle">
        <span class="cookiemanagement__switchToggleValue cookiemanagement__switchToggleValue--on">diakh</span>
        <span class="cookiemanagement__switchToggleValue cookiemanagement__switchToggleValue--off">ara</span>
      </div>
    </div>
  </li>
</ul>



回答3:


Here is an idea with CSS grid where the trick is to make both element inside the same area. You can also keep the same HTML structure.

Relevant code:

.switchToggle {
  ...
  display: grid;
  align-items:center;
  ...
}
.switchToggle > * {
  grid-area:1/1;
}
.switchToggleValue--on {
  padding-right:32px;
}
.switchToggleValue--off {
  padding-left:32px;
  text-align:right;
}

Full code:

.switch {
  display: inline-block;
  position: relative;
  margin:5px;
}
.switchInput {
  cursor: pointer;
  height: 100%;
  opacity: 0;
  position: absolute;
  width: 100%;
  z-index: 1;
}
.switchToggle {
  background-color: #9a3d37;
  border-radius: 50px;
  display: grid;
  align-items:center;
  height: 24px;
  position: relative;
  transition: background-color ease-out 0.3s;
  z-index: 0;
}
.switchToggle > * {
  grid-area:1/1;
}
.switchToggleValue--on {
  padding-right:32px;
}
.switchToggleValue--off {
  padding-left:32px;
  text-align:right;
}
.switchToggle:before {
  content: "";
  background: #fff;
  box-shadow: 1px 0 2px #646464;
  border-radius: 50%;
  border: 1px solid #aaaaaa;
  height: 24px;
  left: 0;
  position: absolute;
  top: 0;
  transition: 0.2s ease-out;
  width: 24px;
  z-index: 2;
}
.switchToggleValue {
  text-transform: uppercase;
  line-height: normal;
  transition: opacity 0.2s ease-out 0.1s;
}
.switchToggleValue--on {
  margin: 0 4px 0 8px;
  opacity: 0;
}
.switchToggleValue--off {
  margin: 0 8px 0 4px;
  opacity: 1;
}
.switchInput:checked ~ .switchToggle {
  background-color: #6a7d39;
}
.switchInput:checked ~ .switchToggle:before {
  left: calc(100% - 24px);
  box-shadow: -1px 0 2px #646464;
}
.switchInput:checked ~ .switchToggle .switchToggleValue--on {
  opacity: 1;
}
.switchInput:checked ~ .switchToggle .switchToggleValue--off {
  opacity: 0;
}
.switchLabel {
  margin-left: 15px;
}
<div class="switch">
    <input class="switchInput" role="switch" type="checkbox" value="3" name="analytics2">
    <div class="switchToggle">
        <span class="switchToggleValue switchToggleValue--on">yes</span>
        <span class="switchToggleValue switchToggleValue--off">no</span>
    </div>
</div>
<br>
<div class="switch">
    <input class="switchInput" role="switch" type="checkbox" value="3" name="analytics2">
    <div class="switchToggle">
        <span class="switchToggleValue switchToggleValue--on">no</span>
        <span class="switchToggleValue switchToggleValue--off">yes</span>
    </div>
</div>
<br>
<div class="switch">
    <input class="switchInput" role="switch" type="checkbox" value="3" name="analytics2">
    <div class="switchToggle">
        <span class="switchToggleValue switchToggleValue--on">diakh</span>
        <span class="switchToggleValue switchToggleValue--off">ara</span>
    </div>
</div>
<br>
<div class="switch">
    <input class="switchInput" role="switch" type="checkbox" value="3" name="analytics2">
    <div class="switchToggle">
        <span class="switchToggleValue switchToggleValue--on">ara</span>
        <span class="switchToggleValue switchToggleValue--off">diakh</span>
    </div>
</div>


来源:https://stackoverflow.com/questions/59973375/make-parent-element-resize-to-equal-the-width-of-the-biggest-of-the-children

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!