Width measures of Text components using a custom font are wrong
See original GitHub issueReact Native version:
System:
OS: macOS 10.14.5
CPU: (12) x64 Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
Memory: 1002.17 MB / 32.00 GB
Shell: 5.3 - /bin/zsh
Binaries:
Node: 10.15.3 - ~/.nvm/versions/node/v10.15.3/bin/node
Yarn: 1.16.0 - /usr/local/bin/yarn
npm: 6.4.1 - ~/.nvm/versions/node/v10.15.3/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
SDKs:
iOS SDK:
Platforms: iOS 12.2, macOS 10.14, tvOS 12.2, watchOS 5.2
Android SDK:
API Levels: 23, 25, 26, 27, 28
Build Tools: 27.0.3, 28.0.2, 28.0.3, 29.0.0
System Images: android-28 | Google APIs Intel x86 Atom, android-28 | Google Play Intel x86 Atom, android-29 | Google Play Intel x86 Atom
Android NDK: 17.2.4988734
IDEs:
Android Studio: 3.4 AI-183.6156.11.34.5522156
Xcode: 10.2.1/10E1001 - /usr/bin/xcodebuild
npmPackages:
react: 16.8.6 => 16.8.6
react-native: 0.60.0 => 0.60.0
⚠️ This is not a regression from RN 0.60, can also be reproduced in RN 0.57.
On Android, some manufacturers — like Samsung, OnePlus, LG, HTC, and others — let you change the default font on your device without having a rooted device, and, of course, rooted devices can also do that.
The <Text>
component provided by React Native doesn’t seem to measure the layout correctly. Observed cases were when the default font is not Roboto and when a thick font weight is applied.
The result is that on these specifics devices, text components with a thicker font weight will be chopped off (seems to be wrapped in some cases?). It could be a dot missing, or even an entire word.
<Text style={{ fontWeight: 'bold' }}>
This looks great!
</Text>
Roboto (Default font) | OnePlus Slate |
---|---|
![]() |
![]() |
Workaround
To influence the layout measures of the text component, we can set a border of at least 2
on it. By doing this, the layout will be properly measured, but the text won’t be vertically centered.
From there, to vertically center the text, we can subtract the double of the border we previously set as a negative marginBottom
. (As seen in the screenshots above).
Issue Analytics
- State:
- Created 4 years ago
- Reactions:24
- Comments:25 (8 by maintainers)
Related, but I’ve noticed that because the wrapping calculation is wrong on custom fonts, sometimes you will get an extra line where the text renderer thinks the text will wrap but doesn’t. There is no way to get rid of it.
Example:
I discovered a “trick” to avoid this kind of issue: don’t rely on
fontWeight
on Android alone! Instead usefontFamily
. Android Roboto have only 6 variants, same for OnePlus Slate. I have spend a few hours trying to find an acceptable combo on stock Android (using a Pixel 3), ColorsOS (Oppo) and OxygenOS (OnePlus)You can safely (on Android) use the following name instead of weight
sans-serif-thin
(= 100/200 depending on android custom font)sans-serif-light
(=300)sans-serif
/sans-serif-regular
(400) (note that OnePlus Slate doesn’t handle sans-serif like sans-serif-regular, when used with a weight)sans-serif-medium
(500)sans-serif-bold
(600/700)sans-serif-black
(800/900)Note that
fontWeight
coupled with afontFamily
give better result on Android, if you want to rely on OS font.Here is a stylesheet you can use safely to think about “weight” and forget about the trick
Just to tag issues so people would find the workaround: #15114 #25258 #29259 #18258 #17629 #21729