Home > OS >  Transforming the parent of 100 divs versus transforming each of its divs?
Transforming the parent of 100 divs versus transforming each of its divs?

Time:06-08

What's the difference between transforming the parent element that contains 100 divs and just transforming each of the parent's divs? Is there a huge performance gap?

<style>
  .parent {
    transform: scale(1.5)
  }
  .child {
    transform: scale(1.5)
  }
</style>
<body>
<div >
   <div ></div>
   …… <!--98 more divs-->
   <div ></div>
</div>
</body>

CodePudding user response:

The difference is that scaling the children won't affect the dimensions of the parent:

.parent {
  background: orange;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  height: 200px;
  gap: 1em;
  width: 50%;
  margin: 0 auto;
  padding: 1em;
}

.child {
  background: red;
}

.parent:hover .child {
  transform: scale(1.05)
}
<div >
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
</div>

Notice how scaling the children visually reduces the gap and the padding.

Compare this to scaling the parent:

.parent {
  background: orange;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  height: 200px;
  gap: 1em;
  padding: 1em;
  width: 50%;
  margin: 0 auto;
}

.child {
  background: red;
}

.parent:hover {
  transform: scale(1.05)
}
<div >
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
</div>

With regard to performance, I wouldn't know how to measure this.

CodePudding user response:

User Agent HTML/CSS parsers are relatively fast, with a 100 elements I would not worry to much about performance issues. While I did not perform a comparison test, I'm sure the difference will be mere milliseconds.

What you should be aware of, though, is the fact that a scaled element will still occupy its original unscaled size:

  • scale down > Shows whitespace around an element. E.g. scale(0.8) shrinks an element to 80% of its original size showing a 20% whitespace around the element.
  • scale up > Will overlap adjacent elements. E.g. scale(1.2) grows the element to 120% of its original size and will overlap 20% of its size over elements around it.

In cases where the above is the desired effect, scaling a parent will scale obviously resize both parent and child elements, as where scaling the child elements only the parent size will remain unchanged.

When the extra whitespace or overlap is undesired, you will need to calculate a negative margin when scaling down, and a regular margin when scaling up. In both cases relative to the scale factor.

Something like (pseudo):

.scale-corrected {
   margin: calc( -1 * (child-height - scale-factorY * child-height) / 2 )
           calc( -1 * (child-width  - scale-factorX * child-width ) / 2 );
   /* this will correct white space/overlap when scaling elements */
}

Update: demo snippet

/************************************************************/
/* SO72544381 https://stackoverflow.com/questions/72544381/ */
/************************************************************/

* { outline: 1px dashed }

.wrapper   { display: flex; flex-flow: row wrap; width: 100% }
.wrapper>* { flex-grow: 1;  min-width: 16rem; font-weight: bold }

h3                   { min-height: 4rem; line-height: 4rem; margin: 0.5rem 0 0 0 }
h3, .wrapper, #cards { background-color: #f5f5f5 }
h3, .wrapper>div>div { text-align: center; padding: 0.5rem 0 }

.parent { transform: scale(0.5); background-color: Silver  }
.child  { transform: scale(0.5); background-color: Tan     }
.large  { transform: scale(1.5); background-color: Thistle }

/************************************************************/

/*****************************/
/* Image scaling slider DEMO */
/*****************************/

/***********/
/* Globals */
/***********/
*           { -webkit-box-sizing: border-box; box-sizing: border-box }
html, body  { width: 100%; max-width: 100% }
body        { margin: 0; min-height: 100vh } /* fully fill the viewport */

label       { padding: 1rem 0 }

/************************************************/
/* element responsive behavior         [STABLE] */
/************************************************/
/* base font size using y = mx   b */
html   { font-size: calc(0.625vmin   0.75rem) } /* (320,14)(1280,20) */

/* Generic page spacers, root font size independent
    T/B: (360,0)(2160, 90) => y = 0.05x -  18 <= base  90, 72 at 1920x1080
    L/R: (640,0)(1920,448) => y = 0.35x - 224 <= base 160, 360x640 full screen
*/
body { padding: calc(5vmin - 18px) calc(35vw - 224px) }

:root {
    --base-aspect-wid:  9; /* some preferred aspect ratio   */
    --base-aspect-hgt: 16; /* alternative to 'aspect-ratio' */

    --base-wid: 10rem; /* width = 10, height = 16/9 * 10, for use in size properties */
    --base-hgt: calc(var(--base-wid) * var(--base-aspect-hgt) / var(--base-aspect-wid));

    --base-scale: 1; /* [0-2] default unscaled, controlled by slider JS */
}

[band],[card] { display: flex }

[band] { /* FBL row of columns, full viewport width */
    flex-flow: row wrap;
    justify-content: center; /* horizontal alignment */
    align-content  : center; /* vertical alignment   */
    width: 100%;
}

[card] { /* FBL column of rows */
    flex-flow: column wrap;
    align-items: center;

    box-shadow: 0px 0px 2px 2px red inset;

    width : var(--base-wid);
    height: var(--base-hgt);
}

[card] img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

[scale] > * {
    transform: scale(var(--base-scale)); /* resize to current scale value */
}
[scale="ok"] > * {
    /* corrective margins relative to current transformation scale */
    margin: calc(-1 * (var(--base-hgt) - var(--base-scale) * var(--base-hgt)) / 2)
            calc(-1 * (var(--base-wid) - var(--base-scale) * var(--base-wid)) / 2);
}
<h3>scale down: whitespace</h3>
<div >
    <div >
       <div>0</div>
       <div>1</div>
       <div>2</div>
       <div>3</div>
       <div>4</div>
       <div>5</div>
       <div>6</div>
       <div>7</div>
       <div>8</div>
       <div>9</div>
    </div>
    <div>
       <div >0</div>
       <div >1</div>
       <div >2</div>
       <div >3</div>
       <div >4</div>
       <div >5</div>
       <div >6</div>
       <div >7</div>
       <div >8</div>
       <div >9</div>
    </div>
</div>

<h3>scale up: overlap and &lt; wrapper overflow &gt;</h3>
<div >
    <div>
        <div >0</div>
        <div >0</div>
        <div >0</div>
    </div>
</div>

<h3>DEMO margins corrected, scale [0-2]</h3>

<label>Card Scale&nbsp;<input type="range" min="0.05" max="2" value="1" step="0.01" oninput="javascript:document.documentElement.style.setProperty('--base-scale', this.value)">&nbsp;</label>

<div band id="cards" scale="ok">
    <div card><img loading="lazy" src="https://picsum.photos/320?random=1" alt="...lazy loading"></div>
    <div card><img loading="lazy" src="https://picsum.photos/320?random=2" alt="...lazy loading"></div>
    <div card><img loading="lazy" src="https://picsum.photos/320?random=3" alt="...lazy loading"></div>
    <div card><img loading="lazy" src="https://picsum.photos/320?random=4" alt="...lazy loading"></div>
    <div card><img loading="lazy" src="https://picsum.photos/320?random=5" alt="...lazy loading"></div>
</div>

<h3>DEMO margins uncorrected</h3>

<div band id="cards" scale>
    <div card><img loading="lazy" src="https://picsum.photos/320?random=1" alt="...lazy loading"></div>
    <div card><img loading="lazy" src="https://picsum.photos/320?random=2" alt="...lazy loading"></div>
    <div card><img loading="lazy" src="https://picsum.photos/320?random=3" alt="...lazy loading"></div>
    <div card><img loading="lazy" src="https://picsum.photos/320?random=4" alt="...lazy loading"></div>
    <div card><img loading="lazy" src="https://picsum.photos/320?random=5" alt="...lazy loading"></div>
</div>

  • Related