CodeKitHub
Инструменты CSS

Генератор теней для React Native

Последнее обновление:

Тени в React Native работают по-разному на каждой платформе: iOS считывает shadowColor, shadowOffset, shadowOpacity и shadowRadius, а Android полностью игнорирует всё это и вместо этого требует отдельное число elevation. Настройте тень визуально здесь и скопируйте объект стилей, охватывающий обе платформы, плюс новую кроссплатформенную строку boxShadow для приложений на New Architecture.

iOS reads the shadow* props; Android ignores them and uses elevation instead — set both so the shadow shows up on both platforms.

Что это за инструмент?

В React Native тени по умолчанию не кроссплатформенны. iOS использует четыре отдельных свойства стиля (shadowColor, shadowOffset с width/height, shadowOpacity от 0 до 1 и shadowRadius для размытия), которые сопоставляются с той же базовой тенью CoreAnimation, что использует box-shadow в вебе. Нативная система View в Android вообще не поддерживает произвольные формы теней — она поддерживает только elevation, единственное число, которое создаёт фиксированную тень в стиле Material Design в зависимости от того, насколько «высоко» view как будто парит.

Это значит, что тень, которая хорошо выглядит на iOS с shadowRadius/shadowOpacity, вообще не отобразится на Android, если не задать также elevation, и они никогда не будут выглядеть попиксельно одинаково, поскольку форма тени elevation не настраивается так, как у iOS. Начиная с React Native 0.74 с включённой New Architecture также доступно кроссплатформенное свойство стиля boxShadow с тем же синтаксисом, что и в CSS.

Зачем его использовать?

  • Живой визуальный предпросмотр при изменении смещения, размытия, прозрачности и цвета — вместо угадывания значений и пересборки приложения для проверки.
  • Получите свойства тени iOS, elevation для Android и новую кроссплатформенную строку boxShadow одновременно, не заглядывая в три разных API.
  • Elevation — отдельный параметр (не вычисляется автоматически из размытия/прозрачности), потому что сопоставление elevation с внешним видом тени на Android не является прямым переводом свойств тени iOS — его нужно подбирать визуально, и этот инструмент позволяет делать это, сравнивая обе платформы бок о бок.
  • Бесплатно, мгновенно и готово к копированию как единый объект стилей.

Как использовать

  1. Настройте смещение по X/Y, радиус размытия, прозрачность и цвет тени — область предпросмотра обновляется в реальном времени.
  2. Отдельно подберите число elevation для Android, пока оно визуально не совпадёт с нужной силой тени.
  3. Нажмите «Copy», чтобы скопировать полный объект стилей, включая свойства iOS, elevation для Android и строку boxShadow.
  4. Вставьте объект в StyleSheet вашего компонента — объедините его с существующими стилями view.

Пример

Ввод

Смещение (0, 4), размытие 8, прозрачность 0.25, чёрный, elevation 5

Результат

shadowColor: '#000000', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.25, shadowRadius: 4, elevation: 5, boxShadow: '0px 4px 8px rgba(0, 0, 0, 0.25)'

shadowRadius устанавливается равным половине значения размытия, показанного в предпросмотре, что соответствует практическому соотношению между радиусом размытия CSS и shadowRadius в iOS.

Часто задаваемые вопросы

Почему моя тень не отображается на Android?

Свойства shadowColor/shadowOffset/shadowOpacity/shadowRadius предназначены только для iOS — нативный рендеринг Android их полностью игнорирует. Нужно также задать свойство elevation (положительное число), чтобы на Android вообще появилась тень.

Можно ли сделать тень на Android идентичной тени на iOS?

Не совсем — elevation создаёт встроенную форму тени Material Design для Android, которая, в отличие от iOS, не настраивается независимо по цвету, направлению смещения или размытию. Можно подобрать число elevation для визуально схожей силы, но попиксельное совпадение между платформами невозможно с классическими API shadow/elevation.

Что такое свойство boxShadow и можно ли использовать его вместо остального?

boxShadow — это более новое, по-настоящему кроссплатформенное свойство стиля (добавлено в React Native 0.74, доступно на New Architecture), использующее тот же строковый синтаксис, что и box-shadow в CSS, и работающее одинаково на iOS и Android. Если версия React Native и архитектура вашего приложения это поддерживают, можно использовать только это одно свойство вместо четырёх отдельных свойств iOS плюс elevation — перед тем как полагаться на него в продакшене, проверьте версию RN и статус New Architecture.

Почему shadowRadius равен половине заданного мной значения размытия?

Живой предпросмотр использует box-shadow из CSS, где значение размытия распространяется примерно вдвое дальше, чем shadowRadius в iOS при том же числе. Сгенерированный код устанавливает shadowRadius равным половине вашего значения размытия, чтобы тень в предпросмотре соответствовала тому, что реально отрисует iOS — если бы вы скопировали значение размытия напрямую, тень на iOS выглядела бы заметно мягче и крупнее, чем в предпросмотре.

Нужен ли Platform.select для применения этих стилей?

Нет — безопасно объединять свойства shadow* для iOS и elevation для Android в одном объекте стилей, именно так, как это делает сгенерированный код: каждая платформа просто игнорирует свойства другой. Platform.select стоит добавлять только если вы хотите действительно разный дизайн теней на каждой платформе, а не только для избежания предупреждений (их и так нет).

Я задал elevation, но тень на Android всё равно не появляется — почему?

Две самые частые причины: у view нет backgroundColor (тень elevation на Android отбрасывается от непрозрачного фона view, поэтому прозрачная view не отбрасывает никакой тени), или у родителя задан overflow: 'hidden', обрезающий тень. Сначала задайте view сплошной цвет фона и проверьте настройки overflow у предков, прежде чем считать, что дело в самом значении elevation.

Похожие инструменты