├── src
├── _globals.sass
├── index.sass
├── components
│ ├── withWindowDimensions
│ │ ├── index.js
│ │ └── withWindowDimensions.js
│ ├── Content
│ │ ├── MobileView.js
│ │ ├── Tile.js
│ │ ├── index.js
│ │ ├── TabbedView.js
│ │ └── DesktopView.js
│ ├── ResponsiveLayout
│ │ └── index.js
│ └── WindowDimensionsProvider
│ │ └── index.js
├── App.test.js
├── App.js
├── index.js
├── data.json
├── logo.svg
├── serviceWorker.js
└── normalize.css
├── public
├── favicon.ico
├── manifest.json
└── index.html
├── .gitignore
├── README.md
└── package.json
/src/_globals.sass:
--------------------------------------------------------------------------------
1 | $primary: #1515F1
2 |
--------------------------------------------------------------------------------
/src/index.sass:
--------------------------------------------------------------------------------
1 | @import 'globals'
2 | @import '~bulma'
3 |
--------------------------------------------------------------------------------
/src/components/withWindowDimensions/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './withWindowDimensions'
2 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pdeona/responsive-layout-hooks/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/src/components/Content/MobileView.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import TabbedView from './TabbedView'
3 |
4 | const MobileView = ({ items }) => (
5 |
6 |
7 |
8 | )
9 |
10 | export default MobileView
11 |
--------------------------------------------------------------------------------
/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | ReactDOM.unmountComponentAtNode(div);
9 | });
10 |
--------------------------------------------------------------------------------
/src/components/ResponsiveLayout/index.js:
--------------------------------------------------------------------------------
1 | import { useWindowDimensions } from '../WindowDimensionsProvider'
2 |
3 | const ResponsiveLayout = ({ breakPoint = 414, renderMobile, renderDesktop }) => {
4 | const { width } = useWindowDimensions()
5 | return width > breakPoint ? renderDesktop() : renderMobile()
6 | }
7 |
8 | export default ResponsiveLayout
9 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Content from './components/Content'
3 | import WindowDimensionsProvider from './components/WindowDimensionsProvider'
4 | import data from './data.json'
5 |
6 | const App = () => (
7 |
8 |
9 |
10 | )
11 |
12 | export default App
13 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": ".",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/src/components/Content/Tile.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | const Tile = ({ className, content, title }) => (
4 |
5 |
6 |
{title}
7 |
{content}
8 |
9 |
10 | )
11 |
12 | export default Tile
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Responsive Layouts with React Hooks
2 |
3 | A companion repo for the corresponding article at [medium.com](https://medium.com/@pedro_19839/simplifying-responsive-layouts-with-react-hooks-19db73893a7a).
4 |
5 | ## Development
6 |
7 | To develop on your computer:
8 |
9 | ```bash
10 | $ git clone https://github.com/pdeona/responsive-layout-hooks
11 | $ cd responsive-layout-hooks
12 | $ yarn
13 | $ yarn start
14 | ```
15 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import './normalize.css'
4 | import './index.sass'
5 | import App from './App'
6 | import * as serviceWorker from './serviceWorker'
7 |
8 | ReactDOM.render(, document.getElementById('root'))
9 |
10 | // If you want your app to work offline and load faster, you can change
11 | // unregister() to register() below. Note this comes with some pitfalls.
12 | // Learn more about service workers: http://bit.ly/CRA-PWA
13 | serviceWorker.unregister()
14 |
--------------------------------------------------------------------------------
/src/components/Content/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ResponsiveLayout from '../ResponsiveLayout'
3 | import MobileView from './MobileView'
4 | import DesktopView from './DesktopView'
5 |
6 | const Content = ({ items }) => {
7 | return (
8 | (
11 |
12 | )}
13 | renderMobile={() => (
14 |
15 | )}
16 | />
17 | )
18 | }
19 |
20 | export default Content
21 |
--------------------------------------------------------------------------------
/src/components/Content/TabbedView.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react'
2 |
3 | const TabbedView = ({ className, items, renderItem }) => {
4 | const [active, setActive] = useState(0)
5 | return (
6 |
7 |
16 |
17 |
18 | {items[active].content}
19 |
20 |
21 |
22 | )
23 | }
24 |
25 | export default TabbedView
26 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "responsive-layouts",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "bulma": "^0.7.4",
7 | "classnames": "^2.2.6",
8 | "node-sass": "^4.11.0",
9 | "react": "^16.8.3",
10 | "react-dom": "^16.8.3",
11 | "react-scripts": "2.1.5"
12 | },
13 | "scripts": {
14 | "start": "react-scripts start",
15 | "build": "react-scripts build",
16 | "test": "react-scripts test",
17 | "eject": "react-scripts eject"
18 | },
19 | "resolutions": {
20 | "merge": "^1.2.1"
21 | },
22 | "eslintConfig": {
23 | "extends": "react-app",
24 | "rules": {
25 | "semi": [
26 | "error",
27 | "never"
28 | ],
29 | "jsx-a11y/anchor-is-valid": "off"
30 | }
31 | },
32 | "browserslist": [
33 | ">0.2%",
34 | "not dead",
35 | "not ie <= 11",
36 | "not op_mini all"
37 | ]
38 | }
39 |
--------------------------------------------------------------------------------
/src/components/Content/DesktopView.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import classNames from 'classnames'
3 | import Tile from './Tile'
4 | import { useWindowDimensions } from '../WindowDimensionsProvider'
5 |
6 | const getClassName = idx => {
7 | switch (idx) {
8 | case 0: return 'is-info'
9 | case 1: return 'is-success'
10 | case 2: return 'is-primary'
11 | case 3: return 'is-danger'
12 | default: return 'is-warning'
13 | }
14 | }
15 |
16 | const DesktopView = ({ items }) => {
17 | const { width } = useWindowDimensions()
18 | return (
19 |
20 |
414 && width < 1088
23 | })}
24 | >
25 | {items.map((item, idx) => (
26 |
27 | ))}
28 |
29 |
30 | )
31 | }
32 |
33 | export default DesktopView
34 |
--------------------------------------------------------------------------------
/src/components/WindowDimensionsProvider/index.js:
--------------------------------------------------------------------------------
1 | import React, { createContext, useContext, useState, useEffect } from 'react'
2 |
3 | export const WindowDimensionsCtx = createContext(null)
4 |
5 | const windowDims = () => ({
6 | height: window.innerHeight,
7 | width: window.innerWidth,
8 | })
9 |
10 | const WindowDimensionsProvider = ({ children }) => {
11 | const [dimensions, setDimensions] = useState(windowDims())
12 | useEffect(() => {
13 | const handleResize = () => {
14 | setDimensions(windowDims())
15 | }
16 | window.addEventListener('resize', handleResize)
17 | return () => { window.removeEventListener('resize', handleResize) }
18 | }, [])
19 | return (
20 |
21 | {children}
22 |
23 | )
24 | }
25 |
26 | export default WindowDimensionsProvider
27 |
28 | export const useWindowDimensions = () => {
29 | return useContext(WindowDimensionsCtx)
30 | }
31 |
--------------------------------------------------------------------------------
/src/data.json:
--------------------------------------------------------------------------------
1 | [
2 | { "title": "Bananas", "content": "Bananas! I will write some great placeholder text – and nobody writes better placeholder text than me, believe me – and I’ll write it very inexpensively. I will write some great, great text on your website’s Southern border, and I will make Google pay for that text. Mark my words. Lorem Ipsum is a choke artist. It chokes!" },
3 | { "title": "Peppers", "content": "Peppers! I will write some great placeholder text – and nobody writes better placeholder text than me, believe me – and I’ll write it very inexpensively. I will write some great, great text on your website’s Southern border, and I will make Google pay for that text. Mark my words. Lorem Ipsum is a choke artist. It chokes!" },
4 | { "title": "Oranges", "content": "Oranges! I will write some great placeholder text – and nobody writes better placeholder text than me, believe me – and I’ll write it very inexpensively. I will write some great, great text on your website’s Southern border, and I will make Google pay for that text. Mark my words. Lorem Ipsum is a choke artist. It chokes!" },
5 | { "title": "Papaya", "content": "Papaya! I will write some great placeholder text – and nobody writes better placeholder text than me, believe me – and I’ll write it very inexpensively. I will write some great, great text on your website’s Southern border, and I will make Google pay for that text. Mark my words. Lorem Ipsum is a choke artist. It chokes!" }
6 | ]
7 |
--------------------------------------------------------------------------------
/src/components/withWindowDimensions/withWindowDimensions.js:
--------------------------------------------------------------------------------
1 | import React, { PureComponent, forwardRef } from 'react'
2 | import { WindowDimensionsCtx } from '../WindowDimensionsProvider'
3 |
4 | const withWindowDimensions = mapDimensionsToProps => WrappedComponent => {
5 | class Wrapped extends PureComponent {
6 | static displayName = `withWindowDimensions(${
7 | WrappedComponent.displayName || WrappedComponent.name
8 | })`
9 |
10 | render() {
11 | const { forwardedRef } = this.props
12 | return (
13 |
14 | {dimensions => (
15 |
20 | )}
21 |
22 | )
23 | }
24 | }
25 |
26 | return forwardRef((props, ref) => )
27 | }
28 |
29 | export default withWindowDimensions
30 |
31 | /**
32 | * sample usage:
33 | *
34 | * import React from 'react'
35 | * import withWindowDimensions from '../withWindowDimensions'
36 | *
37 | * const DumbComponent = ({ width }) => (
38 | * Page is {width} pixels wide.
39 | * )
40 | *
41 | * const mapDimensionsToProps = dimensions => ({
42 | * width: dimensions.width,
43 | * })
44 | *
45 | * export default withWindowDimensions(mapDimensionsToProps)(DumbComponent)
46 | *
47 | */
48 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
15 |
16 |
25 | React App
26 |
27 |
28 |
29 |
30 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/logo.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/serviceWorker.js:
--------------------------------------------------------------------------------
1 | // This optional code is used to register a service worker.
2 | // register() is not called by default.
3 |
4 | // This lets the app load faster on subsequent visits in production, and gives
5 | // it offline capabilities. However, it also means that developers (and users)
6 | // will only see deployed updates on subsequent visits to a page, after all the
7 | // existing tabs open on the page have been closed, since previously cached
8 | // resources are updated in the background.
9 |
10 | // To learn more about the benefits of this model and instructions on how to
11 | // opt-in, read http://bit.ly/CRA-PWA
12 |
13 | const isLocalhost = Boolean(
14 | window.location.hostname === 'localhost' ||
15 | // [::1] is the IPv6 localhost address.
16 | window.location.hostname === '[::1]' ||
17 | // 127.0.0.1/8 is considered localhost for IPv4.
18 | window.location.hostname.match(
19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
20 | )
21 | )
22 |
23 | export function register(config) {
24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
25 | // The URL constructor is available in all browsers that support SW.
26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href)
27 | if (publicUrl.origin !== window.location.origin) {
28 | // Our service worker won't work if PUBLIC_URL is on a different origin
29 | // from what our page is served on. This might happen if a CDN is used to
30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374
31 | return
32 | }
33 |
34 | window.addEventListener('load', () => {
35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`
36 |
37 | if (isLocalhost) {
38 | // This is running on localhost. Let's check if a service worker still exists or not.
39 | checkValidServiceWorker(swUrl, config)
40 |
41 | // Add some additional logging to localhost, pointing developers to the
42 | // service worker/PWA documentation.
43 | navigator.serviceWorker.ready.then(() => {
44 | console.log(
45 | 'This web app is being served cache-first by a service ' +
46 | 'worker. To learn more, visit http://bit.ly/CRA-PWA'
47 | )
48 | })
49 | } else {
50 | // Is not localhost. Just register service worker
51 | registerValidSW(swUrl, config)
52 | }
53 | })
54 | }
55 | }
56 |
57 | function registerValidSW(swUrl, config) {
58 | navigator.serviceWorker
59 | .register(swUrl)
60 | .then(registration => {
61 | registration.onupdatefound = () => {
62 | const installingWorker = registration.installing
63 | if (installingWorker == null) {
64 | return
65 | }
66 | installingWorker.onstatechange = () => {
67 | if (installingWorker.state === 'installed') {
68 | if (navigator.serviceWorker.controller) {
69 | // At this point, the updated precached content has been fetched,
70 | // but the previous service worker will still serve the older
71 | // content until all client tabs are closed.
72 | console.log(
73 | 'New content is available and will be used when all ' +
74 | 'tabs for this page are closed. See http://bit.ly/CRA-PWA.'
75 | )
76 |
77 | // Execute callback
78 | if (config && config.onUpdate) {
79 | config.onUpdate(registration)
80 | }
81 | } else {
82 | // At this point, everything has been precached.
83 | // It's the perfect time to display a
84 | // "Content is cached for offline use." message.
85 | console.log('Content is cached for offline use.')
86 |
87 | // Execute callback
88 | if (config && config.onSuccess) {
89 | config.onSuccess(registration)
90 | }
91 | }
92 | }
93 | }
94 | }
95 | })
96 | .catch(error => {
97 | console.error('Error during service worker registration:', error)
98 | })
99 | }
100 |
101 | function checkValidServiceWorker(swUrl, config) {
102 | // Check if the service worker can be found. If it can't reload the page.
103 | fetch(swUrl)
104 | .then(response => {
105 | // Ensure service worker exists, and that we really are getting a JS file.
106 | const contentType = response.headers.get('content-type')
107 | if (
108 | response.status === 404 ||
109 | (contentType != null && contentType.indexOf('javascript') === -1)
110 | ) {
111 | // No service worker found. Probably a different app. Reload the page.
112 | navigator.serviceWorker.ready.then(registration => {
113 | registration.unregister().then(() => {
114 | window.location.reload()
115 | })
116 | })
117 | } else {
118 | // Service worker found. Proceed as normal.
119 | registerValidSW(swUrl, config)
120 | }
121 | })
122 | .catch(() => {
123 | console.log(
124 | 'No internet connection found. App is running in offline mode.'
125 | )
126 | })
127 | }
128 |
129 | export function unregister() {
130 | if ('serviceWorker' in navigator) {
131 | navigator.serviceWorker.ready.then(registration => {
132 | registration.unregister()
133 | })
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/normalize.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */
2 |
3 | /* Document
4 | ========================================================================== */
5 |
6 | /**
7 | * 1. Correct the line height in all browsers.
8 | * 2. Prevent adjustments of font size after orientation changes in
9 | * IE on Windows Phone and in iOS.
10 | */
11 |
12 | html {
13 | line-height: 1.15; /* 1 */
14 | -ms-text-size-adjust: 100%; /* 2 */
15 | -webkit-text-size-adjust: 100%; /* 2 */
16 | }
17 |
18 | /* Sections
19 | ========================================================================== */
20 |
21 | /**
22 | * Remove the margin in all browsers (opinionated).
23 | */
24 |
25 | body {
26 | margin: 0;
27 | }
28 |
29 | /**
30 | * Add the correct display in IE 9-.
31 | */
32 |
33 | article,
34 | aside,
35 | footer,
36 | header,
37 | nav,
38 | section {
39 | display: block;
40 | }
41 |
42 | /**
43 | * Correct the font size and margin on `h1` elements within `section` and
44 | * `article` contexts in Chrome, Firefox, and Safari.
45 | */
46 |
47 | h1 {
48 | font-size: 2em;
49 | margin: 0.67em 0;
50 | }
51 |
52 | /* Grouping content
53 | ========================================================================== */
54 |
55 | /**
56 | * Add the correct display in IE 9-.
57 | * 1. Add the correct display in IE.
58 | */
59 |
60 | figcaption,
61 | figure,
62 | main { /* 1 */
63 | display: block;
64 | }
65 |
66 | /**
67 | * Add the correct margin in IE 8.
68 | */
69 |
70 | figure {
71 | margin: 1em 40px;
72 | }
73 |
74 | /**
75 | * 1. Add the correct box sizing in Firefox.
76 | * 2. Show the overflow in Edge and IE.
77 | */
78 |
79 | hr {
80 | box-sizing: content-box; /* 1 */
81 | height: 0; /* 1 */
82 | overflow: visible; /* 2 */
83 | }
84 |
85 | /**
86 | * 1. Correct the inheritance and scaling of font size in all browsers.
87 | * 2. Correct the odd `em` font sizing in all browsers.
88 | */
89 |
90 | pre {
91 | font-family: monospace, monospace; /* 1 */
92 | font-size: 1em; /* 2 */
93 | }
94 |
95 | /* Text-level semantics
96 | ========================================================================== */
97 |
98 | /**
99 | * 1. Remove the gray background on active links in IE 10.
100 | * 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
101 | */
102 |
103 | a {
104 | background-color: transparent; /* 1 */
105 | -webkit-text-decoration-skip: objects; /* 2 */
106 | }
107 |
108 | /**
109 | * 1. Remove the bottom border in Chrome 57- and Firefox 39-.
110 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
111 | */
112 |
113 | abbr[title] {
114 | border-bottom: none; /* 1 */
115 | text-decoration: underline; /* 2 */
116 | text-decoration: underline dotted; /* 2 */
117 | }
118 |
119 | /**
120 | * Prevent the duplicate application of `bolder` by the next rule in Safari 6.
121 | */
122 |
123 | b,
124 | strong {
125 | font-weight: inherit;
126 | }
127 |
128 | /**
129 | * Add the correct font weight in Chrome, Edge, and Safari.
130 | */
131 |
132 | b,
133 | strong {
134 | font-weight: bolder;
135 | }
136 |
137 | /**
138 | * 1. Correct the inheritance and scaling of font size in all browsers.
139 | * 2. Correct the odd `em` font sizing in all browsers.
140 | */
141 |
142 | code,
143 | kbd,
144 | samp {
145 | font-family: monospace, monospace; /* 1 */
146 | font-size: 1em; /* 2 */
147 | }
148 |
149 | /**
150 | * Add the correct font style in Android 4.3-.
151 | */
152 |
153 | dfn {
154 | font-style: italic;
155 | }
156 |
157 | /**
158 | * Add the correct background and color in IE 9-.
159 | */
160 |
161 | mark {
162 | background-color: #ff0;
163 | color: #000;
164 | }
165 |
166 | /**
167 | * Add the correct font size in all browsers.
168 | */
169 |
170 | small {
171 | font-size: 80%;
172 | }
173 |
174 | /**
175 | * Prevent `sub` and `sup` elements from affecting the line height in
176 | * all browsers.
177 | */
178 |
179 | sub,
180 | sup {
181 | font-size: 75%;
182 | line-height: 0;
183 | position: relative;
184 | vertical-align: baseline;
185 | }
186 |
187 | sub {
188 | bottom: -0.25em;
189 | }
190 |
191 | sup {
192 | top: -0.5em;
193 | }
194 |
195 | /* Embedded content
196 | ========================================================================== */
197 |
198 | /**
199 | * Add the correct display in IE 9-.
200 | */
201 |
202 | audio,
203 | video {
204 | display: inline-block;
205 | }
206 |
207 | /**
208 | * Add the correct display in iOS 4-7.
209 | */
210 |
211 | audio:not([controls]) {
212 | display: none;
213 | height: 0;
214 | }
215 |
216 | /**
217 | * Remove the border on images inside links in IE 10-.
218 | */
219 |
220 | img {
221 | border-style: none;
222 | }
223 |
224 | /**
225 | * Hide the overflow in IE.
226 | */
227 |
228 | svg:not(:root) {
229 | overflow: hidden;
230 | }
231 |
232 | /* Forms
233 | ========================================================================== */
234 |
235 | /**
236 | * 1. Change the font styles in all browsers (opinionated).
237 | * 2. Remove the margin in Firefox and Safari.
238 | */
239 |
240 | button,
241 | input,
242 | optgroup,
243 | select,
244 | textarea {
245 | font-family: sans-serif; /* 1 */
246 | font-size: 100%; /* 1 */
247 | line-height: 1.15; /* 1 */
248 | margin: 0; /* 2 */
249 | }
250 |
251 | /**
252 | * Show the overflow in IE.
253 | * 1. Show the overflow in Edge.
254 | */
255 |
256 | button,
257 | input { /* 1 */
258 | overflow: visible;
259 | }
260 |
261 | /**
262 | * Remove the inheritance of text transform in Edge, Firefox, and IE.
263 | * 1. Remove the inheritance of text transform in Firefox.
264 | */
265 |
266 | button,
267 | select { /* 1 */
268 | text-transform: none;
269 | }
270 |
271 | /**
272 | * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
273 | * controls in Android 4.
274 | * 2. Correct the inability to style clickable types in iOS and Safari.
275 | */
276 |
277 | button,
278 | html [type="button"], /* 1 */
279 | [type="reset"],
280 | [type="submit"] {
281 | -webkit-appearance: button; /* 2 */
282 | }
283 |
284 | /**
285 | * Remove the inner border and padding in Firefox.
286 | */
287 |
288 | button::-moz-focus-inner,
289 | [type="button"]::-moz-focus-inner,
290 | [type="reset"]::-moz-focus-inner,
291 | [type="submit"]::-moz-focus-inner {
292 | border-style: none;
293 | padding: 0;
294 | }
295 |
296 | /**
297 | * Restore the focus styles unset by the previous rule.
298 | */
299 |
300 | button:-moz-focusring,
301 | [type="button"]:-moz-focusring,
302 | [type="reset"]:-moz-focusring,
303 | [type="submit"]:-moz-focusring {
304 | outline: 1px dotted ButtonText;
305 | }
306 |
307 | /**
308 | * Correct the padding in Firefox.
309 | */
310 |
311 | fieldset {
312 | padding: 0.35em 0.75em 0.625em;
313 | }
314 |
315 | /**
316 | * 1. Correct the text wrapping in Edge and IE.
317 | * 2. Correct the color inheritance from `fieldset` elements in IE.
318 | * 3. Remove the padding so developers are not caught out when they zero out
319 | * `fieldset` elements in all browsers.
320 | */
321 |
322 | legend {
323 | box-sizing: border-box; /* 1 */
324 | color: inherit; /* 2 */
325 | display: table; /* 1 */
326 | max-width: 100%; /* 1 */
327 | padding: 0; /* 3 */
328 | white-space: normal; /* 1 */
329 | }
330 |
331 | /**
332 | * 1. Add the correct display in IE 9-.
333 | * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
334 | */
335 |
336 | progress {
337 | display: inline-block; /* 1 */
338 | vertical-align: baseline; /* 2 */
339 | }
340 |
341 | /**
342 | * Remove the default vertical scrollbar in IE.
343 | */
344 |
345 | textarea {
346 | overflow: auto;
347 | }
348 |
349 | /**
350 | * 1. Add the correct box sizing in IE 10-.
351 | * 2. Remove the padding in IE 10-.
352 | */
353 |
354 | [type="checkbox"],
355 | [type="radio"] {
356 | box-sizing: border-box; /* 1 */
357 | padding: 0; /* 2 */
358 | }
359 |
360 | /**
361 | * Correct the cursor style of increment and decrement buttons in Chrome.
362 | */
363 |
364 | [type="number"]::-webkit-inner-spin-button,
365 | [type="number"]::-webkit-outer-spin-button {
366 | height: auto;
367 | }
368 |
369 | /**
370 | * 1. Correct the odd appearance in Chrome and Safari.
371 | * 2. Correct the outline style in Safari.
372 | */
373 |
374 | [type="search"] {
375 | -webkit-appearance: textfield; /* 1 */
376 | outline-offset: -2px; /* 2 */
377 | }
378 |
379 | /**
380 | * Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
381 | */
382 |
383 | [type="search"]::-webkit-search-cancel-button,
384 | [type="search"]::-webkit-search-decoration {
385 | -webkit-appearance: none;
386 | }
387 |
388 | /**
389 | * 1. Correct the inability to style clickable types in iOS and Safari.
390 | * 2. Change font properties to `inherit` in Safari.
391 | */
392 |
393 | ::-webkit-file-upload-button {
394 | -webkit-appearance: button; /* 1 */
395 | font: inherit; /* 2 */
396 | }
397 |
398 | /* Interactive
399 | ========================================================================== */
400 |
401 | /*
402 | * Add the correct display in IE 9-.
403 | * 1. Add the correct display in Edge, IE, and Firefox.
404 | */
405 |
406 | details, /* 1 */
407 | menu {
408 | display: block;
409 | }
410 |
411 | /*
412 | * Add the correct display in all browsers.
413 | */
414 |
415 | summary {
416 | display: list-item;
417 | }
418 |
419 | /* Scripting
420 | ========================================================================== */
421 |
422 | /**
423 | * Add the correct display in IE 9-.
424 | */
425 |
426 | canvas {
427 | display: inline-block;
428 | }
429 |
430 | /**
431 | * Add the correct display in IE.
432 | */
433 |
434 | template {
435 | display: none;
436 | }
437 |
438 | /* Hidden
439 | ========================================================================== */
440 |
441 | /**
442 | * Add the correct display in IE 10-.
443 | */
444 |
445 | [hidden] {
446 | display: none;
447 | }
448 |
--------------------------------------------------------------------------------