How to set same dynamic width of component child for all instances? Web Components

  • A+
Category:Languages

Assume I have a small component in a web application that represents an expander control, i.e. a header text, an icon to expand / collapse and some content.

A very simple React implementation (pseudo code) could look like this:

const Expander = ({children, title, onExpandToggle, isExpanded}) => (   <div>     <div><span>{title}</span><img src={...} onClick={onExpandToggle} /></div>     {isExpanded && children}   </div> ); 

This implementation shows the icon after the title, so the position of the icon is determined by the length of the title.

It could look something like this:
How to set same dynamic width of component child for all instances? Web Components

Now assume that there are multiple like this below each other. It becomes messy:
How to set same dynamic width of component child for all instances? Web Components

To make this cleaner, all icons should have the same padding from left. The padding should not be fixed but dynamic, so that the longest title determines the position of all icons:
How to set same dynamic width of component child for all instances? Web Components

Assuming that I want to keep the expander in its own component, is there a CSS way to achieve my goal?

So far, I haven't tried anything as I don't have a starting point. In WPF I would have used something like SharedSizeGroup, but this doesn't exist for CSS.

 


Assuming you'll have a container to your component, you can set display: flex to the inner container and align-self: flex-end to your image.

Then wrap your component/s with a div that has display: inline-block which takes the width of the biggest element inside.

Here's an example:

.container{   display: inline-block;   padding: 3px; }  .item{   display: flex;   flex-direction: row;    justify-content: space-between; }  .item .plus{   width: 15px;   height: 15px;   background-image: url("https://cdn1.iconfinder.com/data/icons/mix-color-3/502/Untitled-43-512.png");   background-size: cover;   background-repeat: no-repeat;   align-self: flex-end;   margin-left: 10px; }
<div class="container">   <div class="item">     <div>Synonyms</div>     <div class="plus"></div>   </div>   <div class="item">     <div>Concept</div>     <div class="plus"></div>   </div>   <div class="item">     <div>Term</div>     <div class="plus"></div>   </div> </div>

If you're after a solution that will set all the instances in the page with the same size without them sharing a container you can achieve it with JS.

Calculate the width of each instance, save the biggest, then set this width for the rest of the instances. In this example I'm also highlighting the biggest item. The items are all around the page and can be inside various divs and displays or without any container.

var biggestWidth = 0; var biggestItem;  function setWidth() {   $(".item").each(function() {     var currentWidth = $(this).width();     if (currentWidth > biggestWidth) {       biggestWidth = Math.ceil(currentWidth);       biggestItem = $(this);     }   });    $(".item").width(biggestWidth);   biggestItem.addClass("biggest"); }  $(setWidth());
section {   width: 40%;   float: left;   border: 1px solid black;   border-radius: 3px;   margin: 10px;   padding: 10px; }  .s1 {   background-color: #e5e5e5;   display: table; }  .item {   display: inline-block;   clear: both;   float: left; }  .txt {   float: left;   display: inline-block; }  .plus {   width: 15px;   height: 15px;   background-image: url("https://cdn1.iconfinder.com/data/icons/mix-color-3/502/Untitled-43-512.png");   background-size: cover;   margin-left: 10px;   float: right; }  .shift{   margin-left: 30%; }  .clear{   clear: both; }  .biggest{   background-color: yellow; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <section class="s1">   <div class="item">     <div class="txt">Synonyms</div>     <div class="plus"></div>   </div>   <div class="item">     <div class="txt">Concept</div>     <div class="plus"></div>   </div>   <div class="item">     <div class="txt">Term</div>     <div class="plus"></div>   </div> </section> <section>   <div class="item">     <div class="txt">Synonyms</div>     <div class="plus"></div>   </div>   <div class="item">     <div class="txt">Concept</div>     <div class="plus"></div>   </div>   <div class="item">     <div class="txt">Term</div>     <div class="plus"></div>   </div> </section>  <section>   <div class="item">     <div class="txt">Synonyms - Long</div>     <div class="plus"></div>   </div>   <div class="item">     <div class="txt">Concept</div>     <div class="plus"></div>   </div>   <div class="item">     <div class="txt">Term</div>     <div class="plus"></div>   </div> </section>  <div class="item">   <div class="txt">Synonyms</div>   <div class="plus"></div> </div> <div class="item">   <div class="txt">Concept</div>   <div class="plus"></div> </div> <div class="item">   <div class="txt">Term</div>   <div class="plus"></div> </div>  <div class="clear"></div> <div class="shift"> <div class="item">   <div class="txt">Synonyms</div>   <div class="plus"></div> </div> <div class="item">   <div class="txt">Concept</div>   <div class="plus"></div> </div> <div class="item">   <div class="txt">The bigget item is here</div>   <div class="plus"></div> </div> </div>

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: