翻譯 | 《JavaScript Everywhere》第13章 設置應用程序樣式css
你們好呀,我是毛小悠,是一位前端開發工程師。正在翻譯一本英文技術書籍。html
爲了提升你們的閱讀體驗,對語句的結構和內容略有調整。若是發現本文中有存在瑕疵的地方,或者你有任何意見或者建議,能夠在評論區留言,或者加個人微信:code
_maomao,歡迎相互溝通交流學習。前端
(σ゚∀゚)σ..:*☆哎喲不錯哦react
貓王埃爾維斯·科斯特洛(Elvis Costello
)在1978
年的單曲《嘴脣服務》(Lip Service
)中嘲笑這句話:「不要表現得比我高,而要看着你的鞋子。「這種「親吻」意味着敘述者只要親吻某人的鞋子,就能察覺出他想要得到更高的社會地位,不管他們的西裝多麼考究,衣着多麼高雅。瀏覽器
不論是好是壞,某些風俗是人類文化的重要組成部分,咱們都習慣於接受這些類型的社交方式。考古學家甚至發現,舊石器時代的人類用骨頭,牙齒,漿果和石頭製做了項鍊和手鐲。咱們的衣服不只能夠起到保護人體免受各類元素侵害的功能目的,並且還能夠與他人傳遞有關咱們的文化、社會地位、利益等等的信息。微信
沒有Web
的默認樣式,Web
應用程序仍然能夠正常工做,可是經過應用CSS
,咱們能夠更清晰地與用戶通訊。在本章中,咱們將探討如何使用CSS-in-JS
樣式組件庫將佈局和樣式引入咱們的應用程序。這將使咱們可以在可維護的、基於組件的代碼結構中作出更實用、更美觀的應用程序。網絡
應用程序的許多頁面(在咱們的狀況下是所有)將共享一個通用佈局。例如,咱們應用程序的全部頁面都將具備標題、側邊欄和內容區域(圖13-1
)。react-router
與其在每一個頁面組件中導入共享的佈局元素,咱們能夠建立專門用於咱們的佈局的組件並將每一個頁面組件包裝在其中。app
圖13-1
。頁面佈局的線框框架
爲了建立咱們的組件,咱們將從建立一個新文件src/components/Layout.js
開始。在此文件中,咱們將導入共享組件並佈置內容。咱們的React
組件函數將接收一個children
的屬性,這將告訴咱們在佈局中哪裏放置子元素的內容。
讓咱們在src/components/Layout.js
中建立咱們的組件:
import React from 'react'; import Header from './Header'; import Navigation from './Navigation'; const Layout = ({ children }) => { return ( <React.Fragment> <Header /> <div className="wrapper"> <Navigation /> <main>{children}</main> </div> </React.Fragment> ); }; export default Layout;
如今在src/pages/index.js
文件中,咱們能夠將頁面組件包裝在新建立的Layout
組件中,以將共享佈局應用於每一個頁面:
// import React and routing dependencies import React from 'react'; import { BrowserRouter as Router, Route } from 'react-router-dom'; // import shared layout component import Layout from '../components/Layout'; // import routes import Home from './home'; import MyNotes from './mynotes'; import Favorites from './favorites'; // define routes const Pages = () => { return ( <Router> {/* Wrap our routes within the Layout component */} <Layout> <Route exact path="/" component={Home} /> <Route path="/mynotes" component={MyNotes} /> <Route path="/favorites" component={Favorites} /> </Layout> </Router> ); }; export default Pages;
最後一步是刪除頁面組件中或頁面組件內的全部實例。例如,咱們的src/pages/Home.js
文件如今將具備如下簡化的代碼:
import React from 'react'; const Home = () => { return ( <div> <p>This is the home page</p> </div> ); }; export default Home;
完成此操做後,你能夠在瀏覽器中查看你的應用程序。在路由之間切換時,咱們會在每一個頁面上看到咱們的標題和導航連接。目前,它們還沒有設置樣式,而且咱們的頁面沒有視覺佈局。讓咱們在下一部分中探索添加樣式。
級聯樣式表精確命名:它們是一組規則,容許咱們編寫Web
樣式。樣式爲「層疊」,表示將呈現最後或最明肯定義的樣式。例如:
p { color: green } p { color: red }
該CSS
會將全部段落呈現爲紅色,從而使顏色:綠色規則被覆蓋。這是一個很簡單的想法,可是爲了不錯誤,它產生了許多模式和技術。
BEM
(塊元素修飾符),OOCSS
(面向對象CSS
)和Atomic CSS
等CSS
結構技術使用說明性的類命名來幫助做用域樣式。諸如SASS
(語法很棒的樣式表)和Less
(更精簡的樣式表)之類的預處理器提供了簡化CSS
語法並啓用模塊化文件的工具。儘管它們各有千秋,可是CSS-in-JavaScript
爲開發React
或其餘JavaScript
驅動的應用程序提供了引人注目的用例。
CSS
和UI
框架是開發應用程序的流行選擇,這有充分的理由,它們提供了堅實的樣式基礎,並經過爲常見的應用程序模式提供樣式和功能來減小開發人員須要編寫的代碼量。折衷方案是使用這些框架的應用程序可能在視覺上變得類似,而且可能會增長文件包的大小。可是,這種權衡可能對你來講是值得的。我我的最喜歡使用React
的一些UI
框架是Ant Design
, Bootstrap
, Grommet
, 和 Rebass
CSS-in-JS
當我第一次遇到CSS-in-JS
時,我最初的反應很吃驚。我在Web
標準時代度過了個人Web
開發生涯的初期階段。我繼續倡導Web
開發的可訪問性和合理的逐步加強。十多年來,「關注點分離」一直是個人網絡實踐的核心。所以,若是你像我同樣,只是閱讀「 CSS-in-JS
」會使你感到厭惡,那麼你並不孤單。可是,一旦我進行了適當的(而且沒有判斷力的)嘗試,我很快就被征服了。CSS-in-JS
使咱們能夠輕鬆地將咱們的用戶界面視爲一系列組件,這是多年來我一直在嘗試結合模塊化技術和CSS
預處理器來完成的工做。
在本書中,咱們將使用Styled Components
做爲咱們的CSS-in-JS
庫。它快速、靈活,正在快速發展中,而且是最受歡迎的CSS-in-JS
庫。Airbnb
,Reddit
,Patreon
,Lego
,BBC News
,Atlassian
等公司也使用它。
樣式化組件庫的工做方式是容許咱們使用JavaScript
的模板字符串語法定義元素的樣式。咱們建立一個JavaScript
變量,該變量將引用HTML
元素及其關聯的樣式。因爲聽起來很抽象,因此讓咱們看一個簡單的例子:
import React from 'react'; import styled from 'styled-components' const AlertParagraph = styled.p` color: green; `; const ErrorParagraph = styled.p` color: red; `; const Example = () => { return ( <div> <AlertParagraph>This is green.</AlertParagraph> <ErrorParagraph>This is red.</ErrorParagraph> </div> ); }; export default Example;
如你所見,咱們能夠輕鬆的肯定樣式範圍。此外,咱們將樣式限定到該特定的組件。這有助於咱們避免在應用程序的不一樣部分之間發生類名衝突。
建立一個按鈕組件
如今咱們對樣式化組件有了基本的瞭解,讓咱們將它們集成到咱們的應用程序中。首先,咱們將爲元素編寫一些樣式,這將使咱們可以在整個應用程序中重用該組件。在前面的示例中,咱們將樣式與React/JSX
代碼集成在一塊兒,可是咱們也能夠編寫獨立樣式的組件。首先,在src/components/Button.js
處建立一個新文件,從styled-components
中導入樣式庫,而後將可導出組件設置爲模板字符串,以下所示:
import styled from 'styled-components'; const Button = styled.button` /* our styles will go here */ `; export default Button;
放置好組件後,咱們能夠用一些樣式填充它。添加一些基線按鈕樣式以及懸停和活動狀態樣式,以下所示:
import styled from 'styled-components'; const Button = styled.button` display: block; padding: 10px; border: none; border-radius: 5px; font-size: 18px; color: #fff; background-color: #0077cc; cursor: pointer; :hover { opacity: 0.8; } :active { background-color: #005fa3; } `; export default Button;
如今,咱們能夠在整個應用程序中使用按鈕。例如,要在應用程序的主頁上使用它,咱們能夠導入組件並在一般使用的任何位置使用元素。
在src/pages/home.js
中:
import React from 'react'; import Button from '../components/Button'; const Home = () => { return ( <div> <p>This is the home page</p> <Button>Click me!</Button> </div> ); }; export default Home;
這樣,咱們編寫了一個樣式化的組件,能夠在應用程序中的任何地方使用它。這對於可維護性很是有用,由於咱們能夠輕鬆地找到樣式並在咱們的代碼庫中進行更改。此外,咱們能夠將樣式化的組件與標記耦合在一塊兒,從而容許咱們建立小型、可重用和可維護的組件。
添加全局樣式
儘管咱們的許多樣式將包含在各個組件中,可是每一個站點或應用程序也具備一組全局樣式(諸如CSS
重置,字體和基準顏色之類的東西)。咱們能夠建立一個GlobalStyle.js
組件來容納這些樣式。
這將與以前的示例有所不一樣,由於咱們將建立樣式表,而不是附加到特定HTML
元素的樣式。爲此,咱們將從styled-components
導入createGlobalStyle
模塊。咱們還將導入normalize.css
庫,以確保跨瀏覽器呈現一致的HTML
元素。最後,咱們將爲應用程序的HTML
主體和默認連接樣式添加一些全局規則。
在src/components/GlobalStyle.js
中:
// import createGlobalStyle and normalize import { createGlobalStyle } from 'styled-components'; import normalize from 'normalize.css'; // we can write our CSS as a JS template literal export default createGlobalStyle` ${normalize} *, *:before, *:after { box-sizing: border-box; } body, html { height: 100%; margin: 0; } body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif; background-color: #fff; line-height: 1.4; } a:link, a:visited { color: #0077cc; } a:hover, a:focus { color: #004499; } code, pre { max-width: 100%; } `;
要應用這些樣式,咱們將它們導入到App.js
文件中,並在應用程序中添加元素:
import React from 'react'; import ReactDOM from 'react-dom'; // import global styles import GlobalStyle from '/components/GlobalStyle'; // import routes import Pages from '/pages'; const App = () => { return ( <div> <GlobalStyle /> <Pages /> </div> ); }; ReactDOM.render(<App />, document.getElementById('root'));
這樣,咱們的全局樣式將應用於應用程序。在瀏覽器中預覽應用程序時,你會看到字體已更改,連接具備新樣式以及邊距已刪除(圖13-2
)。
圖13-2
咱們的應用程序如今已應用了全局樣式
組件樣式
如今咱們已經在應用程序中應用了一些全局樣式,咱們能夠開始對單個組件進行樣式化了。在此過程當中,咱們還將介紹應用程序的整體佈局。對於咱們樣式化的每一個組件,咱們首先要從styled-components
導入樣式庫。而後,咱們將一些元素樣式定義爲變量。最後,咱們將在React
組件的JSX
中使用這些元素。
爲了不與HTML
元素髮生衝突,必須將樣式化組件的名稱大寫。
咱們能夠從src/components/Layout.js
開始,在這裏咱們將樣式添加到應用程序佈局的結構和標籤中。
import React from 'react'; import styled from 'styled-components'; import Header from './Header'; import Navigation from './Navigation'; // component styles const Wrapper = styled.div` /* We can apply media query styles within the styled component */ /* This will only apply the layout for screens above 700px wide */ @media (min-width: 700px) { display: flex; top: 64px; position: relative; height: calc(100% - 64px); width: 100%; flex: auto; flex-direction: column; } `; const Main = styled.main` position: fixed; height: calc(100% - 185px); width: 100%; padding: 1em; overflow-y: scroll; /* Again apply media query styles to screens above 700px */ @media (min-width: 700px) { flex: 1; margin-left: 220px; height: calc(100% - 64px); width: calc(100% - 220px); } `; const Layout = ({ children }) => { return ( <React.Fragment> <Header /> <Wrapper> <Navigation /> <Main>{children}</Main> </Wrapper> </React.Fragment> ); }; export default Layout;
隨着咱們Layout.js
成分齊全,咱們能夠在咱們Header.js
和Navigation.js
文件添加一些樣式:
在src/components/Header.js
中:
import React from 'react'; import styled from 'styled-components'; import logo from '../img/logo.svg'; const HeaderBar = styled.header` width: 100%; padding: 0.5em 1em; display: flex; height: 64px; position: fixed; align-items: center; background-color: #fff; box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.25); z-index: 1; `; const LogoText = styled.h1` margin: 0; padding: 0; display: inline; `; const Header = () => { return ( <HeaderBar> <img src={logo} alt="Notedly Logo" height="40" /> <LogoText>Notedly</LogoText> </HeaderBar> ); }; export default Header;
最後,在src/components/Navigation.js
中:
import React from 'react'; import { Link } from 'react-router-dom'; import styled from 'styled-components'; const Nav = styled.nav` padding: 1em; background: #f5f4f0; @media (max-width: 700px) { padding-top: 64px; } @media (min-width: 700px) { position: fixed; width: 220px; height: calc(100% - 64px); overflow-y: scroll; } `; const NavList = styled.ul` margin: 0; padding: 0; list-style: none; line-height: 2; /* We can nest styles in styled-components */ /* The following styles will apply to links within the NavList component */ a { text-decoration: none; font-weight: bold; font-size: 1.1em; color: #333; } a:visited { color: #333; } a:hover, a:focus { color: #0077cc; } `; const Navigation = () => { return ( <Nav> <NavList> <li> <Link to="/">Home</Link> </li> <li> <Link to="/mynotes">My Notes</Link> </li> <li> <Link to="/favorites">Favorites</Link> </li> </NavList> </Nav> ); }; export default Navigation;
應用這些樣式後,咱們如今有了一個徹底樣式化的應用程序(圖13-3
)。展望將來,咱們能夠在建立單個組件時應用樣式。
圖13-3
。咱們的應用程序已應用樣式
在本章中,咱們嚮應用程序介紹了佈局和樣式。使用CSS-in-JS
庫中的Styled Components
,咱們能夠編寫簡明扼要的CSS
樣式。而後,能夠將這些樣式應用於單個組件,也能夠應用於整個應用程序。在下一章中,咱們將經過實現GraphQL
客戶端並調用咱們的API
來開發功能齊全的應用程序。
若是有理解不到位的地方,歡迎你們糾錯。若是以爲還能夠,麻煩你點贊收藏或者分享一下,但願能夠幫到更多人。