Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
@expo/html-elements
Advanced tools
Universal semantic HTML React components for iOS, Android, web, and desktop
Simple, light-weight, and well tested, universal semantic HTML elements as React components for iOS, Android, web, and desktop apps!
We at Expo recommend using platform agnostic primitives like View
, Image
, and Text
whenever possible but sometimes that's not easy. Some primitives like Tables, and Footers are native to web only and currently have no way of easily accessing. This package aims to solve that while still being an optimal UI package for iOS, and Android.
@expo/html-elements
will optimize your website for SEO and accessibility. Meaning your websites are indexed more accurately and your native apps better accommodate physically impaired users.
react-native-web
a11y rules whenever possible.H1
component will render an <h1 />
on web, a UILabel
on iOS, and a TextView
on Android.StyleSheet
API.href
on a Text
element.jest-expo-enzyme
. Each element is also E2E tested on iOS with Detox, and web with jest-expo-puppeteer
.Install:
yarn add @expo/html-elements
Import and use the package:
import { H1 } from '@expo/html-elements';
Here is a list of all the currently supported elements and the web feature they map to. Not all HTML elements are supported. There are some HTML elements that mostly overlap with some universal modules, you should always try to use the universal modules whenever possible. All supported components are a capitalized variation of the semantic HTML they implement/emulate.
Other features not implemented in this package can be found in different parts of the Expo ecosystem.
HTML | Universal | Package |
---|---|---|
<audio /> | Audio | expo-av |
<button /> | <Button /> | react-native |
<input type="text" /> | <TextInput /> | react-native |
<input type="file" /> | ImagePicker | expo-image-picker |
<input type="file" /> | DocumentPicker | expo-document-picker |
<canvas /> | <GLView /> | expo-gl & Expo Canvas |
<iframe /> | <WebView /> | <WebView /> . @react-native-community/web-view is not maintained by Expo and doesn't have web support |
<link /> | None | Eject the index.html with npx expo customize and link resources directly with <link /> |
<noscript /> | None | Eject the index.html with npx expo customize and use <noscript /> directly as HTML |
<div /> | <View /> | react-native |
<img /> | <Image /> | react-native |
<span /> | <Text /> | react-native |
<video /> | <Video /> | expo-av |
style="backdrop-filter" | <BlurView /> | expo-blur |
style="linear-gradient()" | <LinearGradient /> | expo-linear-gradient |
Header elements will use the expected font size and margins from web universally. You can see how the native CSS units (rem, and em) are transformed in css/units.
import { H1, H2, H3, H4, H5, H6 } from '@expo/html-elements';
<H1/>
import { H1 } from '@expo/html-elements';
export default () => <H1>Example<H1/>
Platform | Output |
---|---|
Web | <h1 aria-level="1" dir="auto" role="heading" /> |
Native | <Text accessibilityRole="header" style={[Custom]} /> |
<H2/>
import { H2 } from '@expo/html-elements';
export default () => <H2>Example<H2/>
Platform | Output |
---|---|
Web | <h2 aria-level="2" dir="auto" role="heading" /> |
Native | <Text accessibilityRole="header" style={[Custom]} /> |
<H3/>
import { H3 } from '@expo/html-elements';
export default () => <H3>Example<H3/>
Platform | Output |
---|---|
Web | <h3 aria-level="3" dir="auto" role="heading" /> |
Native | <Text accessibilityRole="header" style={[Custom]} /> |
<H4/>
import { H4 } from '@expo/html-elements';
export default () => <H4>Example<H4/>
Platform | Output |
---|---|
Web | <h4 aria-level="4" dir="auto" role="heading" /> |
Native | <Text accessibilityRole="header" style={[Custom]} /> |
<H5/>
import { H5 } from '@expo/html-elements';
export default () => <H5>Example<H5/>
Platform | Output |
---|---|
Web | <h5 aria-level="5" dir="auto" role="heading" /> |
Native | <Text accessibilityRole="header" style={[Custom]} /> |
<H6/>
import { H6 } from '@expo/html-elements';
export default () => <H6>Example<H6/>
Platform | Output |
---|---|
Web | <h6 aria-level="6" dir="auto" role="heading" /> |
Native | <Text accessibilityRole="header" style={[Custom]} /> |
<A/>
You can use the anchor element with href prop to open links. On native this will attempt to use the Linking
API to open the href
.
<Text />
react-native-web-hooks
| tutorialimport { A } from '@expo/html-elements';
export default () => <A href="#" target="_blank" />;
}
Platform | Output |
---|---|
Web | <a data-focusable="{true}" dir="auto" href="#" role="link" target="_blank" /> |
Native | <Text accessibilityRole="link" onPress={[Function]} /> |
You can use layout elements like Header, Main, Footer, Section, Nav, etc. as a drop-in replacement for View
s in your existing app.
All layout HTML elements inherit the shared style of <View />
to accommodate the Yoga layout engine which we use on native for iOS, and Android.
display
is always flex
. This is because Yoga only implements display: flex
.flex-direction
is always column
instead of row
.Consider the following: in your app you have a basic element at the top which wraps the buttons and title. A screen reader doesn't understand that this is a header, and mostly neither does a web crawler. But if you replace the encasing view with a <Header />
the following happens:
UIView
uses UIAccessibilityTraitHeader
.View
will use the proper AccessibilityNodeInfoCompat.CollectionItemInfoCompat
| docs.<header />
with the ARIA role
set to "banner"
.Some elements like Footer
and Main
have no iOS, or Android enhancements, but they'll still improve web. Using the proper HTML 5 elements will make your layout compliant with the HTML5 outline algorithm.
<Nav/>
import { Nav } from '@expo/html-elements';
export default () => <Nav />;
Platform | Output |
---|---|
Web | <nav style="display:flex" /> |
Native | <View /> |
<Header/>
Renders a <header />
on web with ARIA set to banner
and a View
with ARIA set to header
on mobile.
import { Header } from '@expo/html-elements';
export default () => <Header />;
Platform | Output |
---|---|
Web | <header role="banner" /> |
Native | <View /> |
iOS | UIView uses UIAccessibilityTraitHeader . |
Android | View will use the proper AccessibilityNodeInfoCompat.CollectionItemInfoCompat docs |
<Main/>
Renders a <main />
on web with ARIA role
set to main
and a View
with no ARIA set on mobile.
import { Main } from '@expo/html-elements';
export default () => (
<Main>
<P>Some content in the main element</P>
</Main>
);
)
Platform | Output |
---|---|
Web | <main role="main" style="display:flex" /> |
Native | <View /> |
<Section/>
Renders a <section />
on web with ARIA set to region
and a View
with ARIA set to summary
on mobile.
import { Section } from '@expo/html-elements';
export default () => <Section />;
Platform | Output |
---|---|
Web | <section role="region" style="display:flex" /> |
Native | <View accessibilityRole="summary" /> |
<Article/>
Renders an <article />
on web and a View
everywhere else.
import { Article } from '@expo/html-elements';
export default () => <Article />;
Platform | Output |
---|---|
Web | <article role="article" /> |
Native | <View /> |
<Aside/>
import { Aside } from '@expo/html-elements';
export default () => <Aside />;
Platform | Output |
---|---|
Web | <aside role="complementary" /> |
Native | <View /> |
<Footer/>
Renders an <footer />
on web and a View
everywhere else.
import { Footer } from '@expo/html-elements';
export default () => <Footer />;
Platform | Output |
---|---|
Web | <footer role="contentinfo" /> |
Native | <View /> |
Text elements currently use Text
universally rendering either a div
or span
to emulate Yoga style properly.
Code
, and Pre
).StyleSheet
API.import { P, B, S, I, BR, Code } from '@expo/html-elements';
export default () => (
<>
<P>
Hello<B>World (in bold)</B>
</P>
<S>strike text</S>
<BR />
<I>Italic</I>
<Code>const foo = true</Code>
</>
);
<P/>
Standard paragraph element.
Platform | Output |
---|---|
Universal | <Text style={{ fontSize: 14, marginVertical: '1em' }} /> |
<B/>
Bold text text.
Platform | Output |
---|---|
Universal | <Text style={{ fontWeight: 'bold' }} /> |
<Strong/>
Alternate bold text.
Platform | Output |
---|---|
Universal | <Text style={{ fontWeight: 'bold' }} /> |
<S/>
Strike through text.
Platform | Output |
---|---|
Universal | <Text style={{ textDecorationLine: 'line-through' }} /> |
<Del/>
Alternate strike through text.
Platform | Output |
---|---|
Universal | <Text style={{ textDecorationLine: 'line-through' }} /> |
<I/>
Italic text.
Platform | Output |
---|---|
Universal | <Text style={{ fontStyle: 'italic' }} /> |
<EM/>
Alternate italic text.
Platform | Output |
---|---|
Universal | <Text style={{ fontStyle: 'italic' }} /> |
<Code/>
Inline code block with fontFamily: 'Courier'
on iOS and Web, fontFamily: 'monospace'
on Android.
Platform | Output |
---|---|
Universal | <Text style={[Custom]} /> |
<Pre/>
Render a preformatted code block with fontFamily: 'Courier'
on iOS and Web, fontFamily: 'monospace'
on Android.
<Pre>{`
body {
color: red;
}
`}</Pre>
// Or pass views
<Pre>
<Code>{`const val = true`}</Code>
</Pre>
Platform | Output |
---|---|
Universal | <Text style={[Custom]} /> | <View /> |
<Mark/>
Highlight text.
Platform | Output |
---|---|
Universal | <Text style={{ backgroundColor: 'yellow', color: 'black' }} /> |
<Q/>
Quoted text.
Platform | Output |
---|---|
Universal | <Text style={[Custom]}>"{props.children}"</Text> |
<BlockQuote/>
Platform | Output |
---|---|
Universal | <View style={[Custom]} /> |
<Time/>
dateTime
prop is supported on web and stripped on native.Platform | Output |
---|---|
Universal | <Text style={[Custom]} /> |
Lists can be used to create basic bulleted or numbered lists. You should try and use universal FlatList
or SectionList
components for long scrolling lists instead of these.
<UL/>
Create an unordered (bulleted) list <ul />
on web, and emulates the style with a <View />
on native.
import { UL, LI } from '@expo/html-elements';
export default () => (
<UL>
<LI>oranges</LI>
<LI>apples</LI>
<UL>
<LI>green</LI>
<LI>red</LI>
</UL>
</UL>
);
Platform | Output |
---|---|
Web | <ul /> |
Native | <View style={[Custom]} /> |
<LI/>
Create a standard list item <li />
on web and a native view on mobile which can render text or views inside it.
Platform | Output |
---|---|
Web | <li /> |
Native | <Text style={[Custom]} /> | <View style={[Custom]} /> |
<HR/>
Renders a <View>
everywhere. Style is modified to match web.
import { HR } from '@expo/html-elements';
export default () => <HR />;
Platform | Output |
---|---|
Web | <hr /> |
Native | <View style={[Custom]} /> |
<BR/>
Create a line break.
Platform | Output |
---|---|
Web | <br /> |
Native | <View style={{height: 8, width: 0}} /> |
Create tables universally.
padding
is removed from all table elements.TH
and TD
on mobile.colSpan
and rowSpan
are currently web-only (PRs welcome).import { Table, THead, TH, TBody, TFoot, TR, TD, Caption } from '@expo/html-elements';
import { Text } from 'react-native';
export default () => (
<Table>
<Caption>Caption</Caption>
<THead>
<TR>
<TH colSpan="2">The table header</TH>
</TR>
</THead>
<TBody>
<TR>
<TD>The table body</TD>
<TD>with two columns</TD>
</TR>
</TBody>
<TFoot>
<TR>
<TD>
<Text>This is the table footer</Text>
</TD>
</TR>
</TFoot>
</Table>
);
<table>
<caption>
Caption
</caption>
<thead>
<tr>
<th colspan="2">The table header</th>
</tr>
</thead>
<tbody>
<tr>
<td>The table body</td>
<td>with two columns</td>
</tr>
</tbody>
<tfoot>
<tr>
<td><div>The table body</div></td>
</tr>
</tfoot>
</table>
<Table/>
Base element for creating a Table.
Platform | Output |
---|---|
Web | <table /> |
Native | <View style={[Custom]} /> |
<THead/>
Header element in a Table.
Platform | Output |
---|---|
Web | <thead /> |
Native | <View style={[Custom]} /> |
<TBody/>
Body element in a Table.
Platform | Output |
---|---|
Web | <tbody /> |
Native | <View style={[Custom]} /> |
<TFoot/>
Footer element in a Table.
Platform | Output |
---|---|
Web | <tfoot /> |
Native | <View style={[Custom]} /> |
<TH/>
Used to display text in the Header.
colSpan
and rowSpan
are currently web-only.Platform | Output |
---|---|
Web | <th /> |
Native | <Text style={[Custom]} /> |
<TR/>
Used to create a Row in a Table.
Platform | Output |
---|---|
Web | <tr /> |
Native | <View style={[Custom]} /> |
<TD/>
Create a cell in a Table.
colSpan
and rowSpan
are currently web-only.Platform | Output |
---|---|
Web | <td /> |
Native | <View style={[Custom]} /> |
<Caption/>
Used to caption your table. Excepts text as a child.
Platform | Output |
---|---|
Web | <caption /> |
Native | <Text style={[Custom]} /> |
Contributions are very welcome! Please refer to guidelines described in the contributing guide.
FAQs
Universal semantic HTML React components for iOS, Android, web, and desktop
We found that @expo/html-elements demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.