Styling Components


FlexBox, inline styling and styled-components

Innovative Solutions and Technologies Center(ISTC)

Yerevan, Armenia

By Edgar Aroutiounian, Summer 2017

Progress:

Making a real application


So far we have only made Components on bland HTML elements. HTML elements however only describe the content of our application. They don't talk about layout or styling.

Styling and intelligent layout is what will make our applications really shine and show quality work.

https://alistapart.com/article/indefenseofeyecandy

Layout using CSS, the point of it


You should start by understanding the Browser's model for showing elements on the screen. To the browser, everything is a box.

https://developer.mozilla.org/en-US/docs/Learn/CSS/Introduction_to_CSS/Box_model

Elements are either blocks or inline by default, this roughly means that block elements will start a new line whereas inline elements will stay on the same line. An Example of a block element is a <p> tag, example of inline is <span>.

We can control this with CSS with the display property

p { display: inline; }

Controlling the layout of our application is critical to making a great user experience and having the UI adapt to whatever screen size we might encounter (Responsive design)

Styling in React


Of course we can style our Components as well using existing CSS

const Banner = () => (
  <nav className={'top-nav-bar'}>
    <p className={'top-nav-bar-elem'}>First</p>
    <p className={'top-nav-bar-elem'}>Second</p>
  </nav>
)

Notice that unlike HTML we write in .html files, we said 'className' instead of class. That is because class is a reserved keyword in JavaScript

Styling in React cont...


We can also apply styling directly to elements and this is called inline-styling.

const AboutMe = ({pageMaker}) => {
  const me_style = {fontSize: '24px',  fontFamily: 'Optima'};
  return <p style={me_style}>{pageMaker}</p>;
};

This will end up creating a HTML element that will look like this in the web browser

<p style='font-size:24px; font-family:Optima'>

Notice that the key names in the JavaScript object are camel cased (fontFamily). This is because JavaScript keynames, identifiers can't have a - in their name. Keep this in mind when you're reading CSS docs and trying to write the styles as an object.

Flexbox overview


Flexbox is a 2 dimensional layout algorithm. We turn it on with 'display: flex' in our container elements.

render () {
  return (
    <div style={{display: 'flex'}}>
      <p>first</p>
      <p>second</p>
    </div>
  )
}

The enclosing div is now the flex container and the child elements are the flex children. This is an important distinction because once we turn on flex, then some properties only make sense for the parent and some only do for the child.

Flexbox overview cont...


Flexbox makes many traditionally hard things to do in CSS (vertical centering) very easy to do. Flexbox is so nice that Facebook reimplemented the algorithm for ReactNative and it is the only layout system available there.

On web, the default direction of flex is row oriented, you can control that property with 'flex-direction' on the container element (The element with display: flex). The alternative is to make it column oriented, that is to make the children elements be displayed from top to bottom instead of left to right, try it!

// Change flexDirection to 'row', see what happens
// Also change justifyContent to space-around or space-between
return (
  <div style={{display: 'flex', justifyContent: 'center',
               flex: 1, flexDirection: 'column', height: '400px'}}>
    <p style={{padding: '1rem', backgroundColor:'aliceblue'}}>First</p>
    <p style={{padding: '1rem', backgroundColor:'aliceblue'}}>Second</p>
    <p style={{padding: '1rem', backgroundColor:'aliceblue'}}>Third</p>
  </div>
);

Flexbox overview cont...


Learning Flexbox is one of the most important web technologies.

Avoid too many tutorials, all you really need is to study this page over and over again, along with lots of practice.

https://css-tricks.com/snippets/css/a-guide-to-flexbox/

CSS in JS


Traditionally, web applications separated out the HTML from CSS and from JavaScript. Since React, the whole landscape has changed and now we are adding all that logic seemingly in the same place, with Components. Now we have shown inline styling but inline styling has some limitation, namely that we can't do CSS pseduo-selectors and media queries.

https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries

https://developer.mozilla.org/en/docs/Web/CSS/Pseudo-classes

With React Components though, you can get around this by using className and still having some CSS style sheets.

Styled Components


Quite a few libraries have come about to solve this problem of CSS in JS, along with the limitations of inline-styling; we will emphasis styled-components.

$ yarn add styled-components

styled-components takes the idea of React to the next level allowing us to add styling as a reusable Component. As an added benefit, styled-components also works on React-Native.

Be sure to read the docs after this lecture

https://www.styled-components.com/docs

styled-components, cont...


import styled from 'styled-components';

const BoxWrapper = styled.div`
  display: flex;
  height: 400px;
  justify-content: space-around;
`;

const content = (
  <BoxWrapper>
    <p>Hello</p>
    <p>World</p>
  </BoxWrapper>
);

Let's break this down. Noticed that we used styled.div with two backticks. This is a regular feature of the JavaScript language. It is actually a function call to the styled.div function. Also notice that the CSS we use in the template string is 100% CSS, with all the power of CSS, this means we can use media queries, and pseudo-selectors with no problems and now whenever we make a BoxWrapper component, it will have this CSS applied to it with a real CSS class. Just we don't make that class name for the div, it will be auto generated for us by styled-components.

styled-components, cont...


const TextContent = styled.p`
  padding: 1rem;
  text-align: center;
  background-color: red;
  &:hover {
    background-color: orange;
  }
`;
const make_text = t => <TextContent>{t}</TextContent>;
const content = (
  <BoxWrapper>
    {make_text('Hello')}
    {make_text('World')}
  </BoxWrapper>
);

See the '&:hover'? Its technically not legal CSS but styled-components allows us to use the sass syntax helpers. Try this out.

styled-components, cont...


Notice that the components made by styled components are plain React components, this means that we can also even pass props to them!

const TextContent = styled.p`
  padding: 1rem;
  text-align: center;
  color: ${props => props.main === true ? 'orange': 'blue'};
  background-color: red;
`;
// Or even shorter in the styled.p call
// color: ${({main}) => main === true ? 'orange': 'blue'};

const make_main_text = t => <TextContent main={true}>{t}</TextContent>;

Since remember that props is just a JavaScript Object passed to components when they are created, we can just object destructure on them immediately

styled-components, cont...


We can also override styles!

const TextWithMorePadding = styled(TextContent)`
  padding: 1.75rem;
`;

This will take the styled component that we previously made, the TextContent and it will override the padding of 1rem but the newer 1.75rem while still keeping the other CSS values. This way we can easily make base components of styling and then make other, specialized Components.I recommend making a single styles.js file where you place all your styled-components and then export them for your project

import styled from 'styled-components';
const TextContent = styled.p`
  padding: 1rem;
  text-align: center;
  color: ${({main}) => main === true ? 'orange': 'blue'};
  background-color: red;
`;
export { TextContent };