⬆️ ⬇️

CSS in JavaScript: the future of component styles



Using the built-in styles, you can get all the software features of JavaScript, which gives us advantages in the form of a CSS pre-processor (variables, impurities and functions), and also helps solve many problems that arise in CSS, such as namespace conflicts and styling.



For more information on CSS problems solved in JavaScript, you can watch the presentation of React CSS in JS ( React CSS in JS ), or to learn about performance improvements with Aphrodite, read Inline CSS at Khan Academy: Aphrodite . If you want to learn more about the best CSS practices in JavaScript, check out the Airbnb ( Airbnb's styleguide ) guide .



Here we will talk about using embedded JavaScript styles to create components that allow you to solve basic design problems, which I mentioned earlier in the article “Before you master the design, you need to familiarize yourself with the basics” ( Before you can master design, .



Motivating example



: . , : Button ButtonStyles. , — (view). , .



:



...

function Button(props) {
  return (
    <input
      type="button"
      className={css(styles.button)}
      value={props.text}
    />
  );
}


— React-. className — Aphrodite . CSS styles CSS. styles StyleSheet.create Aphrodite ({...}). StyleSheet.create ({...}) Aphrodite (Aphrodite playground).



:



...

const gradient = 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)';

const styles = StyleSheet.create({
  button: {
    background: gradient,
    borderRadius: '3px',
    border: 0,
    color: 'white',
    height: '48px',
    textTransform: 'uppercase',
    padding: '0 25px',
    boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .30)',
  },
});


— Aphrodite. border-radius borderRadius, . , — . , .



:



image

— Aphrodite



, Aphrodite . , .



№ 1.



— . . Sass Less, Aphrodite JavaScript JSON.





. , , , displayLarge, h2. , , semibold, , 600.



export const fontSize = {
  // heading
  displayLarge: '32px',
  displayMedium: '26px',
  displaySmall: '20px',
  heading: '18px',
  subheading: '16px',

  // body
  body: '17px',
  caption: '15px',
};

export const fontWeight = {
  bold: 700,
  semibold: 600,
  normal: 400,
  light: 200,
};

export const tagMapping = {
  h1: 'displayLarge',
  h2: 'displayMedium',
  h3: 'displaySmall',
  h4: 'heading',
  h5: 'subheading',
};

export const lineHeight = {
  // heading
  displayLarge: '48px',
  displayMedium: '48px',
  displaySmall: '24px',
  heading: '24px',
  subheading: '24px',

  // body
  body: '24px',
  caption: '24px',
};


, , . — , .



« — ?» (Why is Vertical Rhythm an Important Typography Practice?).



image



. . « : » (Typography can make or break your design: a process for choosing type), . (Modular Scale), , (vertical rhythm calculator).





, , . — .



import React, { PropTypes } from 'react';
import { StyleSheet, css } from 'aphrodite/no-important';
import { tagMapping, fontSize, fontWeight, lineHeight } from '../styles/base/typography';

function Heading(props) {
  const { children, tag: Tag } = props;
  return <Tag className={css(styles[tagMapping[Tag]])}>{children}</Tag>;
}

export default Heading;

export const styles = StyleSheet.create({
  displayLarge: {
    fontSize: fontSize.displayLarge,
    fontWeight: fontWeight.bold,
    lineHeight: lineHeight.displayLarge,
  },
  displayMedium: {
    fontSize: fontSize.displayMedium,
    fontWeight: fontWeight.normal,
    lineHeight: lineHeight.displayLarge,
  },
  displaySmall: {
    fontSize: fontSize.displaySmall,
    fontWeight: fontWeight.bold,
    lineHeight: lineHeight.displaySmall,
  },
  heading: {
    fontSize: fontSize.heading,
    fontWeight: fontWeight.bold,
    lineHeight: lineHeight.heading,
  },
  subheading: {
    fontSize: fontSize.subheading,
    fontWeight: fontWeight.bold,
    lineHeight: lineHeight.subheading,
  },
});


Heading — , . , .



...
export const tagMapping = {
  h1: 'displayLarge',
  h2: 'displayMedium',
  h3: 'displaySmall',
  h4: 'heading',
  h5: 'subheading',
};


styles. .



export const styles = StyleSheet.create({
  displayLarge: {
    fontSize: fontSize.displayLarge,
    fontWeight: fontWeight.bold,
    lineHeight: lineHeight.displayLarge,
  },

  ...
});


Heading :



function Parent() {
  return (
    <Heading tag="h2">Hello World</Heading>
  );
}


. , . , Heading, Text .



№ 2.



, . , , .





, . spacingFactor, . .



const spacingFactor = 8;
export const spacing = {
  space0: `${spacingFactor / 2}px`,  // 4
  space1: `${spacingFactor}px`,      // 8
  space2: `${spacingFactor * 2}px`,  // 16
  space3: `${spacingFactor * 3}px`,  // 24
  space4: `${spacingFactor * 4}px`,  // 32
  space5: `${spacingFactor * 5}px`,  // 40
  space6: `${spacingFactor * 6}px`,  // 48

  space8: `${spacingFactor * 8}px`,  // 64
  space9: `${spacingFactor * 9}px`,  // 72
  space13: `${spacingFactor * 13}px`, // 104
};


. , , , , . , , spacingFactor .



 (1:1.618)
8.0 x (1.618 ^ 0) = 8.000
8.0 x (1.618 ^ 1) = 12.94
8.0 x (1.618 ^ 2) = 20.94
8.0 x (1.618 ^ 3) = 33.89
8.0 x (1.618 ^ 4) = 54.82
8.0 x (1.618 ^ 5) = 88.71


. .



const spacingFactor = 8;
export const spacing = {
  space0: `${computeGoldenRatio(spacingFactor, 0)}px`,  // 8
  space1: `${computeGoldenRatio(spacingFactor, 1)}px`,  // 13
  space2: `${computeGoldenRatio(spacingFactor, 2)}px`,  // 21
  space3: `${computeGoldenRatio(spacingFactor, 3)}px`,  // 34
  space4: `${computeGoldenRatio(spacingFactor, 4)}px`,  // 55
  space5: `${computeGoldenRatio(spacingFactor, 5)}px`,  // 89
};

function computeGoldenRatio(spacingFactor, exp) {
  return Math.round(spacingFactor * Math.pow(1.618, exp));
}


. — .



, marginBottom Button.



import { spacing } from '../styles/base/spacing';

...

const styles = StyleSheet.create({
  button: {
    marginBottom: spacing.space4, // adding margin using spacing constant
    ...
  },
});


. , marginBottom ?



— . Spacing .



import React, { PropTypes } from 'react';
import { spacing } from '../../base/spacing';

function getSpacingSize(size) {
  return `space${size}`;
}

function Spacing(props) {
  return (
    <div style={{ marginBottom: spacing[getSpacingSize(props.size)] }}>
      {props.children}
    </div>
  );
}

export default Spacing;


, . , .



, , (cards), margin, . , , .



, , , marginBottom. , , . « » (Single-direction margin declarations).



, .



import React, { PropTypes } from 'react';
import { StyleSheet, css } from 'aphrodite/no-important';
import { spacing } from '../../styles/base/spacing';

function Card(props) {
  return (
    <div className={css(styles.card)}>
      {props.children}
    </div>
  );
}

export default Card;

export const styles = StyleSheet.create({
  card: {
    padding: spacing.space4}, // using spacing constants as padding

    background: 'rgba(255, 255, 255, 1.0)',
    boxShadow: '0 3px 17px 2px rgba(0, 0, 0, .05)',
    borderRadius: '3px',
  },
});


.



:



image



, CSS JavaScript, . JavaScript . , (view), .



')

Source: https://habr.com/ru/post/329710/



All Articles