How to break through browser 12px restrictions

At present, Chrome browser still does not release the 12px limit, but Chrome is still the browser with the largest number of users.

When I was developing a project, I had a whim: what if I actually need 11px font size? This is not possible in Chrome. About fonts, I first thought of non PX units such as rem. However, REM is only for responsive adaptation and cannot break through this limitation.

em, REM and other units are only conversion units proposed for displaying effects at different resolutions. The common library px2rem only uses js to convert PX to rem. Including rpx units proposed by wechat applet!

This road is impassable, and there is only one way left: change the visual size rather than the actual size.

theoretical basis

css has an attribute: transform: scale();

  • If the absolute value of the value is > 1, it is magnified. For example, 2 is magnified twice
  • If the absolute value of the value is 0 < 1, it is reduced. For example, 0.5 is 0.5 times the original value;
  • A negative value indicates that the graph is flipped.

By default, scale(x, y): scale on the x/y axis; If y has no value, y==x by default;
You can also write separately: scalex() scaley() scalez(), when writing separately, you can scale the Z axis

The second writing method: transform: scale3d(x, y, z). This writing method is a compound writing method of the above method, and the result is the same as the above.

But one thing to note when using this attribute: scale is based on "the center point of the space where the element is scaled".
Therefore, if it is used in the scene of changing the visual size of an element, it is generally necessary to use another element to "restore the position":

transform-origin: top left;

Syntactically, transform origin has three attribute values:

transform-origin: x-axis y-axis z-axis;

The default is:

transform-origin:50% 50% 0;

Attribute values can be specific values such as percentage, em and px, or keywords such as top, right, bottom, left and center. The function is to change the origin of an element deformation.

practical application

<div class="mmcce__info-r">
  <!-- some html structure -->
  <div v-show="xxx" class="mmcce-valid-mj-period" :class="{'mmcce-mh': showStr}" @click="handleShowStr"> <!-- click Whether the event control is displayed or not -->
    <div class="mmcce-valid-period-child">{{couponInfo.startTimeFormat}}-{{couponInfo.endTimeFormat}}</div><!-- Parent structure, click to display the following content -->
    <div class="mmcce-valid-pro" ref="mmcceW" :style="{opacity: showStr ? 1 : 0}">
      <!-- The following contents will be explained later -->
      <div class="mmcce-text" 
        v-for="(item, index) in couponInfo.thresholdStr" 
        :key="index" 
        :index="index"
        :style="{height: mTextH[index] + 'px'}"
      >{{item}}</div>
    </div>
  </div>
</div>
.mmcce-valid-mj-period {
  max-height: 15px;
  transition: all .2s ease;

  &.mmcce-mh {
    max-height: 200px;
  }

  .mmcce-valid-pro {
    display: flex;
    flex-direction: column;
    padding-bottom: 12px;

    .mmcce-text {
      width: 200%;
      font-size: 22px;
      height: 15px;
      line-height: 30px;
      color: #737373;
      letter-spacing: 0;
      transform       : scale(.5);
      transform-origin: top left;
    }
  }
}

.mmcce-valid-period-child {
  position: relative;
  width      : 200%;
  white-space: nowrap;
  font-size  : 22px;
  color      : #979797;
  line-height: 30px;

  transform       : scale(.5);
  transform-origin: top left;

  //xxx
}

It can be clearly stated that such a hack needs to specify the height value of the scaling element!

Why in the above code In the mmcce valid MJ period class, use Max height? Why expand the text class in the element Use height in mmcce text?
I will class After the height in mmcce text is removed, see the following effect:

OK, you can see that the accounting height is not "scaled" as we want. Affects the position of the following elements.

In essence, it is "the visual size has changed, but the actual size has not changed".

It should be noted that in general, you can explicitly set a height value greater than or equal to its font size for the scaled element.

Other problems caused by scaling

This problem may not be considered in the scenes used by many people: after being limited by the height of the scaled elements, if the elements wrap, there will be text overlap.

To this end, I use the method of obtaining the width of the parent element in the mounted life cycle, then dynamically calculating whether to wrap lines and the number of lines to wrap lines, and finally re rendering the height value of each piece of data with dynamic style.
Here are three points to note:

  1. Here is a clever method: use the visual font size value of each text * the length of the string. Because the scene encountered by the author will not have problems, it can be used like this. In uncertain scenarios, it is more recommended to use canvas or dom to actually calculate the width of each character and then make judgment (you need to know that the widths of words, letters and numbers are different);
  2. Attention should be paid to the display of some special models, such as Samsung's galaxy fold. This thing is a folding screen, and its calculation will be inconsistent with the general screen calculation;
  3. In the vue life cycle, mounted can operate dom, but cannot obtain the actual dom elements; You can use this$ Get element. However, it should be noted that the elements obtained during this period cannot use v-if (that is, they must exist in the virtual tree). This is also the reason why the author uses v-show and opacity in the above code.

On the third point, there is a question of timing. For example, a pop-up window is displayed when you first enter the page. The pop-up window is a component. What are you doing This component cannot be obtained in Vue. (this has nothing to do with v-if or v-show) but you can also split the header, and then call the methods exposed by the pop-up component in the mounted of the header component.

mounted(){
  let thresholdStr = this.info.dropDownTextList;
  let minW = false;
  if(this.$el.querySelector('.mmcce-valid-pro').clientWidth < 140) { // Models that are less than the element width of the iPhone 5 will be subject to special treatment
    minW = true
  }
  let mmcw = this.$el.querySelector('.mmcce-valid-pro').getBoundingClientRect().width;

  let mmch = [];

  for(let i=0;i<thresholdStr.length;i++) {
    // 11 refers to the font size value of the scaled text, which is a clever way
    if(11*(thresholdStr[i].length) > mmcw) {
      if(minW) {
        mmch[i] = Math.floor((11*thresholdStr[i].length) / mmcw) * 15;
      }else {
        mmch[i] = Math.floor((11*(thresholdStr[i].length) + 40) / mmcw) * 15;
      }
    }else {
      mmch[i] = 15;
    }
  }

  this.mTextH = mmch;
},

Keywords: Javascript Vue.js css chrome transform

Added by excl209 on Wed, 22 Dec 2021 21:00:21 +0200