Slide 1

Slide 1 text

Dealing with CSS universally 1

Slide 2

Slide 2 text

Hi, I'm Simon @simonvocella https://github.com/voxsim 2

Slide 3

Slide 3 text

One day.. npx create-react-app my-app cd my-app npm start 3

Slide 4

Slide 4 text

import React, { Component } from 'react'; import logo from './logo.svg'; import './App.css'; class App extends Component { render() { return (
logo

Welcome to React

To get started, edit src/App.js and save to reload.

); } } export default App; App.js 4

Slide 5

Slide 5 text

.App { text-align: center; } .App-logo { height: 80px; } .App-header { background-color: #222; height: 150px; padding: 20px; color: white; } .App-title { font-size: 1.5em; } .App-intro { font-size: large; } App.css 5

Slide 6

Slide 6 text

6

Slide 7

Slide 7 text

7

Slide 8

Slide 8 text

8

Slide 9

Slide 9 text

React Native for Web implements the React Native style API in a way that avoids all the problems with CSS at scale: https://github.com/necolas/react-native-web/blob/master/website/guides/style.md https://speakerdeck.com/vjeux/react-css-in-js No code minification. No sharing of constants. Non-deterministic resolution. No isolation. No local variables. Implicit dependencies. No dead code elimination. 9

Slide 10

Slide 10 text

10

Slide 11

Slide 11 text

11

Slide 12

Slide 12 text

yarn add styled-components 12

Slide 13

Slide 13 text

import React, { Component } from 'react'; import logo from './logo.svg'; import './App.css'; import styled from "styled-components"; const AppHeader = styled.div` background-color: #222; height: 150px; padding: 20px; color: white; `; App.js 13

Slide 14

Slide 14 text

class App extends Component { render() { return (
logo

Welcome to React

To get started, edit src/App.js and save to reload.

); } } export default App1; App.js 14

Slide 15

Slide 15 text

import React, { Component } from 'react'; import logo from './logo.svg'; import './App.css'; import styled from "styled-components"; const AppHeader = styled.div` background-color: #222; height: 150px; padding: 20px; color: white; `; const Logo = styled.img` height: 80px; `; const AppIntro = styled.p` font-size: large; `; ... App.js 15

Slide 16

Slide 16 text

class App extends Component { render() { return ( Welcome to React To get started, edit src/App.js and save to reload. ); } } export default App1; App.js 16

Slide 17

Slide 17 text

yarn add react-native-scripts 17

Slide 18

Slide 18 text

{ "name": "css-universal-app", "version": "0.1.0", "private": true, "dependencies": { "expo": "^26.0.0", "react": "^16.3.2", "react-dom": "^16.3.2", "react-native": "^0.54.2", "react-native-scripts": "^1.13.1", "react-native-svg-uri": "^1.2.3", "react-scripts": "1.1.4", "styled-components": "^3.2.5" }, "main": "./src/App.mobile.js", "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject", "ios": "react-native-scripts ios" } } package.json 18

Slide 19

Slide 19 text

import React, { Component } from 'react'; import logo from './logo.svg'; import styled from "styled-components"; import { Text, View, Image } from "react-native"; const AppHeader = styled.Viewdiv` background-color: #222; height: 150px; padding: 20px; color: white; `; const Logo = styled.Imageimg` height: 80px; `; const AppIntro = styled.Textp` font-size: 18pxlarge; `; ... App.mobile.js 19

Slide 20

Slide 20 text

It works but it still sucks.. 20

Slide 21

Slide 21 text

App.mobile.js App.web.js 21

Slide 22

Slide 22 text

App.web.js App.mobile.js 22

Slide 23

Slide 23 text

const makeApp = () => { const AppHeader = styled('div')` background-color: #222; height: 150px; padding: 20px; color: white; `; const Logo = styled('img')` height: 80px; `; const AppIntro = styled('p')` font-size: 18px; `; ... return class App extends Component { ... } App.core.js 23

Slide 24

Slide 24 text

import App from './App.core'; export default App(); App.web.js 24

Slide 25

Slide 25 text

const makeApp = (platformComponent) => { const AppHeader = styled(platformComponent('div'))` background-color: #222; height: 150px; padding: 20px; color: white; `; const Logo = styled(platformComponent('img'))` height: 80px; `; const AppIntro = styled(platformComponent('p'))` font-size: 18px; `; ... return class App extends Component { ... } App.core.js 25

Slide 26

Slide 26 text

import App from './App.core'; const webComponent = component => component; export default App(webComponent); App.web.js 26

Slide 27

Slide 27 text

App.mobile.js import Expo from 'expo'; import App from './App.core'; import React from 'react'; import {View, Text} from 'react-native'; import SvgUri from 'react-native-svg-uri'; if (process.env.NODE_ENV === 'development') { Expo.KeepAwake.activate(); } const mobileComponent = (component) => { const reactToReactNative = { 'div': View, 'p': Text, 'img': ({src, alt}) => }; return reactToReactNative[component]; } Expo.registerRootComponent(App(mobileComponent)); 27

Slide 28

Slide 28 text

28

Slide 29

Slide 29 text

29

Slide 30

Slide 30 text

const makeApp = () => { const AppHeader = styled('div')` background-color: #222; height: 150px; padding: 20px; color: white; align-items: center; justify-content: center; flex: 1; `; const Logo = styled('img')` height: 80px; `; ... const Title = styled('p')` font-size: 18px; color: white; `; ... return class App extends Component { ... } App.core.js 30

Slide 31

Slide 31 text

31

Slide 32

Slide 32 text

32

Slide 33

Slide 33 text

https://github.com/voxsim/css-universal- app 33

Slide 34

Slide 34 text

@simonvocella https://github.com/voxsim 34

Slide 35

Slide 35 text

Thank you 35