Понимание мобильного терминала 1px|От базовых принципов до решений с открытым исходным кодом

CSS
Понимание мобильного терминала 1px|От базовых принципов до решений с открытым исходным кодом

предисловие

Недавно, когда я писал мобильное приложение H5, я столкнулся с моментом, который стоит отметить. Теперь от его происхождения до реализации, давайте поговорим о 1px на мобильной стороне, сказав, что 1px недостаточно точен, следует сказать 1физический пиксель.

Прочитав следующие статьи, вы поймете следующие вопросы:

вопрос

  • Почему проблема с 1px?
  • Каковы способы достижения 1px? Каковы преимущества и недостатки этих методов?
  • Какие решения используются в проектах с открытым исходным кодом?
  • Как решить проблемы, связанные с 1PX в проекте?

источник

основная концепция

Во-первых, нам нужно понять две концепции, одна из которыхпиксельможно сократить какpx, другойСоотношение пикселей устройства (DPR)

像素 :指在由一个数字序列表示的图像中的一个最小单元,单位是 px,不可再次分割了。

设备像素比(DPR): 设备像素比 = 设备像素 / 设备独立像素。

Позвольте мне объяснить следующие несколько концепций.

  • Пиксель CSS (виртуальный пиксель): относится к логическому пикселю, используемому в коде стилей CSS.В спецификации CSS единицы длины можно разделить на две категории: абсолютные единицы и относительные единицы. px — это относительная единица относительно пикселей устройства.
  • Пиксель устройства (физический пиксель): Относится к наименьшей физической единице, которой устройство может управлять дисплеем, что означает точки на дисплее. Со дня изготовления экрана на заводе количество пикселей устройства на нем фиксируется, что связано с размером экрана.
  • Аппаратно-независимый пиксель (логический пиксель): его можно рассматривать как точку в компьютерной системе координат, эта точка представляет собой виртуальный пиксель, который может использоваться программой (например, пиксель CSS), эта точка не имеет фиксированного размера, чем он меньше, тем четче. Затем соответствующая система преобразует его в физические пиксели.

То есть, когда логический пиксель имеет размер 1, он отображается как физический пиксель размером 2 пикселя на устройстве с DPR, равным 2.

Справочные данные

Параметры различных типов экранных устройств iphone

Примечание. Коэффициент масштабирования здесь является значение DRP

Данные для сравнения проектов

Некоторым людям будет любопытно, почему черновик дизайна показывает 750x1334, это потому, что черновик дизайна отображаетсяфизический пиксель

И пиксели в нашем cssлогический пиксельДолжно быть 375 x 667, установите пользовательскую ширину 375 пикселей при написании кода.

Тогда параметр css, фактически представленный шириной 1 пиксель в проекте дизайна, должен быть 0,5 пикселя, что соответствует физическому пикселю в 1 пиксель, так как же реализовать физический пиксель в 1 пиксель?

упражняться

В конечном счете, есть два решения, одно из которых — использовать css вtransfrom:scaleY(0.5), другой — задать масштабирование медиа-запроса в соответствии с различными параметрами DPR.

Решение первое

принцип

Псевдоэлементы с использованием css::after + transfromувеличить

Зачем использовать псевдоэлементы?из-за псевдоэлементов::afterили::beforeОн не зависит от текущего элемента и может масштабироваться независимо, не влияя на масштабирование самого элемента.

Псевдоэлементы Большинство браузеров также могут использовать одинарные кавычки по умолчанию в той же форме, что и псевдоклассы, и совместимость с одинарными кавычками (т.е.) лучше

выполнить

<div class="cell border-1px"> cell <div>

<style>
.cell {
    width: 100px;
    height: 100px;
}
<!--全部边框-->
.border-1px:after {
    content: '';
    position: absolute;
    box-sizing: border-box;
    top: 0;
    left: 0;
    width: 200%;
    height: 200%;
    border: 1px solid #000;
    border-radius: 4px;
    -webkit-transform: scale(0.5);
    transform: scale(0.5);
    -webkit-transform-origin: top left;
}

<!--单边框,以上边框为例-->
.border-1px-top:before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    border-top: 1px solid red;
    transform: scaleY(.5);
    transform-origin: left top;
}
</style>

Решение 2 (Обновление решения 1)

принцип

Используйте less для инкапсуляции общего кода (схема 1) и добавьте медиа-запросы для выполнения различного масштабирования на устройствах с разными DPR.

.border(
    @borderWidth: 1px; 
    @borderStyle: solid; 
    @borderColor: @lignt-gray-color; 
    @borderRadius: 0) {
    position: relative;
    &:before {
        content: '';
        position: absolute;
        width: 98%;
        height: 98%;
        top: 0;
        left: 0;
        transform-origin: left top;
        -webkit-transform-origin: left top;
        box-sizing: border-box;
        pointer-events: none;
    }
    @media (-webkit-min-device-pixel-ratio: 2) {
        &:before {
            width: 200%;
            height: 200%;
            -webkit-transform: scale(.5);
        }
    }
    @media (-webkit-min-device-pixel-ratio: 2.5) {
        &:before {
            width: 250%;
            height: 250%;
            -webkit-transform: scale(.4);
        }
    }
    @media (-webkit-min-device-pixel-ratio: 2.75) {
        &:before {
            width: 275%;
            height: 275%;
            -webkit-transform: scale(1 / 2.75);
        }
    }
    @media (-webkit-min-device-pixel-ratio: 3) {
        &:before {
            width: 300%;
            height: 300%;
            transform: scale(1 / 3);
            -webkit-transform: scale(1 / 3);
        }
    }
    .border-radius(@borderRadius);
    &:before {
        border-width: @borderWidth;
        border-style: @borderStyle;
        border-color: @borderColor;
    }
}

.border-all(
	@borderWidth: 1px; 
	@borderStyle: solid; 
	@borderColor: @lignt-gray-color; 
	@borderRadius: 0) {
    .border(@borderWidth; @borderStyle; @borderColor; @borderRadius);
}

Другие варианты:

  • Используйте изображения: лучшая совместимость, худшая гибкая линия, не может изменить цвет, длину
  • использоватьviewportа такжеrem,jsдинамическое изменениеviewportсерединаscaleZoom, недостаток в том, что он не работает с существующими проектами, например: используйтеvhа такжеvwмакет
        <meta name="viewport" id="WebViewport" content="initial-scale=1,    maximum-scale=1, minimum-scale=1, user-scalable=no">
    
  • Используйте CSS-градиентыlinear-gradientилиbox-shadow

Вышеуказанные три схемы имеют фатальные недостатки и пока не рекомендуются

совместимость

Последний взгляд, как совместимость, в основном псевдоэлементы,transform:scaleа такжеmin-device-pixel-ratioСовместимость этих ключевых слов

Решения библиотеки с открытым исходным кодом

библиотека компонентов Ванта

Перейти на github для просмотра соответствующего кода

использоватьlessнаписано


.hairline-common() {
  position: absolute;
  box-sizing: border-box;
  content: ' ';
  pointer-events: none;
}

.hairline(@color: @border-color) {
  .hairline-common();

  top: -50%;
  right: -50%;
  bottom: -50%;
  left: -50%;
  border: 0 solid @color;
  transform: scale(0.5);
}

тоже первое решение

библиотека компонентов ant-design-mobile

Перейти на github для просмотра соответствующего кода

.scale-hairline-common(@color, @top, @right, @bottom, @left) {
  content: '';
  position: absolute;
  background-color: @color;
  display: block;
  z-index: 1;
  top: @top;
  right: @right;
  bottom: @bottom;
  left: @left;
}

.hairline(@direction, @color: @border-color-base) when (@direction = 'top') {
  border-top: 1PX solid @color;

  html:not([data-scale]) & {
    @media (min-resolution: 2dppx) {
      border-top: none;

      &::before {
        .scale-hairline-common(@color, 0, auto, auto, 0);
        width: 100%;
        height: 1PX;
        transform-origin: 50% 50%;
        transform: scaleY(0.5);

        @media (min-resolution: 3dppx) {
          transform: scaleY(0.33);
        }
      }
    }
  }
}

.hairline(@direction, @color: @border-color-base) when (@direction = 'right') {
  border-right: 1PX solid @color;

  html:not([data-scale]) & {
    @media (min-resolution: 2dppx) {
      border-right: none;

      &::after {
        .scale-hairline-common(@color, 0, 0, auto, auto);
        width: 1PX;
        height: 100%;
        background: @color;
        transform-origin: 100% 50%;
        transform: scaleX(0.5);

        @media (min-resolution: 3dppx) {
          transform: scaleX(0.33);
        }
      }
    }
  }
}
.hairline(@direction, @color: @border-color-base) when (@direction = 'bottom') {
  border-bottom: 1PX solid @color;
  html:not([data-scale]) & {
    @media (min-resolution: 2dppx) {
      border-bottom: none;
      &::after {
        .scale-hairline-common(@color, auto, auto, 0, 0);
        width: 100%;
        height: 1PX;
        transform-origin: 50% 100%;
        transform: scaleY(0.5);
        @media (min-resolution: 3dppx) {
          transform: scaleY(0.33);
        }
      }
    }
  }
}

.hairline(@direction, @color: @border-color-base) when (@direction = 'left') {
  border-left: 1PX solid @color;

  html:not([data-scale]) & {
    @media (min-resolution: 2dppx) {
      border-left: none;

      &::before {
        .scale-hairline-common(@color, 0, auto, auto, 0);
        width: 1PX;
        height: 100%;
        transform-origin: 100% 50%;
        transform: scaleX(0.5);

        @media (min-resolution: 3dppx) {
          transform: scaleX(0.33);
        }
      }
    }
  }
}

.hairline(@direction, @color: @border-color-base, @radius: 0) when (@direction = 'all') {
  border: 1PX solid @color;
  border-radius: @radius;

  html:not([data-scale]) & {
    @media (min-resolution: 2dppx) {
      position: relative;
      border: none;

      &::before {
        content: '';
        position: absolute;
        left: 0;
        top: 0;
        width: 200%;
        height: 200%;
        border: 1PX solid @color;
        border-radius: @radius * 2;
        transform-origin: 0 0;
        transform: scale(0.5);
        box-sizing: border-box;
        pointer-events: none;

        // @media (min-resolution: 3dppx) {
        //   width: 300%;
        //   height: 300%;
        //   border-radius: @radius * 3;
        //   transform: scale(0.33);
        // }
      }
    }
  }
}

Это стоит изучить, и оно немного отличается от vant и первого решения, главным образом тем, что оно обрабатывает два случая с DPR 2 и 3, что является более полным по сравнению с ним.

Здесь PX пишется с большой буквы, чтобы плагины не конвертировали px в rem и другие единицы.

Суммировать

Благодаря этой статье вы, вероятно, понимаете все тонкости проблемы 1px, а также понимаете, как решать связанные проблемы.Если эта статья может решить ваши сомнения или проблемы на работе, вы можете поставить лайк и добавить ее в закладки.

В связи с ограниченным техническим уровнем, если в статье есть какая-либо ошибка, укажите ее в комментариях, спасибо!

Далее я должен поговорить оПроблемы верстки Mobile H5 и некоторые подводные камниДля резюме учебной работы, вы можете обратить внимание.


обновить:Проблема с макетом H5 для мобильных устройствзавершенный

обновить:Мобильная серия шаговых ям H5завершенный