8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

React UI library の antd について (2) - Layout

Last updated at Posted at 2019-07-05

React UI library の antd について (1) - Button
React UI library の antd について (2) - Layout
React UI library の antd について (3) - redux-form


前回は antd のインストールとButton componentを見ました。簡単には使えましたが、BootstrapやMaterial-UIとの差があまりわかりませんでした。
React UI library の antd について (1) - Button

今回はLayoutを見ますが、他のUIライブラリと比べると、コードが論理的にスッキリと書けるような気がします。

#1.Grid

Antd Grid システム

antd の Grid システムは以下のルールに従います。

  • 行を row で表し、row の中に複数の列 col を配置します。
  • colの中にコンテンツを配置します。row 直下の要素は col 以外は置けません。
  • 各rowの中に24個までのcolを配置できます。24個を超えた場合は、溢れたcolは改行されます。
  • Grid システムはFlex layoutをサポートしています。

1-1.シンプルな例

src/App.js
import React, { Component } from 'react';
import { Row, Col } from 'antd';
import './App.css';

const style1 = { background: "#66CDAA", padding: "20px", fontWeight: "bold" }
const style2 = { background: "#AFEEEE", padding: "20px" , fontWeight: "bold"}

class App extends Component {

  render() {
    return (
      <div style={{ margin: '10px'}}>
        <Row style={{ margin: '10px'}}>
          <Col span={12} style={style1}>col-12</Col>
          <Col span={12} style={style2}>col-12</Col>
        </Row>
        <Row style={{ margin: '10px'}}>
          <Col span={8} style={style1}>col-8</Col>
          <Col span={8} style={style2}>col-8</Col>
          <Col span={8} style={style1}>col-8</Col>
        </Row>
        <Row style={{ margin: '10px'}}>
          <Col span={6} style={style1}>col-6</Col>
          <Col span={6} style={style2}>col-6</Col>
          <Col span={6} style={style1}>col-6</Col>
          <Col span={6} style={style2}>col-6</Col>
        </Row>
      </div>
    );
  }
}

export default App;

以下が実行例です。

image.png

1-2.Flex Layout

Flex Layoutを使うには、Rowで**type="flex"**を指定し、justifyでLayout ( start end center space-around space-between ) を指定します。

src/App.js
import React, { Component } from 'react';
import { Row, Col } from 'antd';
import './App.css';

const style1 = { background: "#66CDAA", padding: "20px", fontWeight: "bold" }
const style2 = { background: "#AFEEEE", padding: "20px" , fontWeight: "bold"}

class App extends Component {

  render() {
    return (
      <div style={{ margin: '10px'}}>
        <p>sub-element align left</p>
        <Row type="flex" justify="start" style={{ margin: '10px'}}>
          <Col span={4} style={style1}>col-4</Col>
          <Col span={4} style={style2}>col-4</Col>
          <Col span={4} style={style1}>col-4</Col>
          <Col span={4} style={style2}>col-4</Col>
        </Row>

        <p>sub-element align center</p>
        <Row type="flex" justify="center" style={{ margin: '10px'}}>
          <Col span={4} style={style1}>col-4</Col>
          <Col span={4} style={style2}>col-4</Col>
          <Col span={4} style={style1}>col-4</Col>
          <Col span={4} style={style2}>col-4</Col>
        </Row>

        <p>sub-element align right</p>
        <Row type="flex" justify="end" style={{ margin: '10px'}}>
          <Col span={4} style={style1}>col-4</Col>
          <Col span={4} style={style2}>col-4</Col>
          <Col span={4} style={style1}>col-4</Col>
          <Col span={4} style={style2}>col-4</Col>
        </Row>

        <p>sub-element monospaced arrangement</p>
        <Row type="flex" justify="space-between" style={{ margin: '10px'}}>
          <Col span={4} style={style1}>col-4</Col>
          <Col span={4} style={style2}>col-4</Col>
          <Col span={4} style={style1}>col-4</Col>
          <Col span={4} style={style2}>col-4</Col>
        </Row>

        <p>sub-element align full</p>
        <Row type="flex" justify="space-around" style={{ margin: '10px'}}>
          <Col span={4} style={style1}>col-4</Col>
          <Col span={4} style={style2}>col-4</Col>
          <Col span={4} style={style1}>col-4</Col>
          <Col span={4} style={style2}>col-4</Col>
        </Row>
      </div>
    );
  }
}

export default App;

以下のように表示されます。

image.png

##1-3. レスポンシブデザイン

レスポンシブデザインはBootstrap流の指定で実現できます。以下のコードと実行結果を参照してください。

src/App.js
import React, { Component } from 'react';
import { Row, Col } from 'antd';
import './App.css';

const style1 = { background: "#66CDAA", padding: "20px", fontWeight: "bold" }
const style2 = { background: "#AFEEEE", padding: "20px" , fontWeight: "bold"}

class App extends Component {

  render() {
    return (
      <Row style={{ margin: '10px'}}>
        <Col xs={2} sm={4} md={6} lg={8} xl={10} style={style1}>
          Col
        </Col>
        <Col xs={20} sm={16} md={12} lg={8} xl={4} style={style2}>
          Col
        </Col>
        <Col xs={2} sm={4} md={6} lg={8} xl={10} style={style1}>
          Col
        </Col>
      </Row>
    );
  }
}

export default App;

以下ブラウザのサイズごとのレイアウトです。レスポンシブデザインが実現できていることが確認できます。

画面サイズ=xl
image.png

画面サイズ=lg
image.png

画面サイズ=md
image.png

画面サイズ=sm
image.png

画面サイズ=xs
image.png

##1-4. 簡単なplayground - column数とgutter.

Sliderで、gutterとcolumn数を変化させ、レイアウトが動的に変わっていくのを確認します。

Rowの属性であるgutterはgrid間のスペースを指定するものです。Col間のスペースというよりは、Colのコンテンツ(以下の例ではdiv)間のスペースを取ってくれます。セレクタ [class~='ant-col'] > div で指定されるコンテンツ間のスペースです。

src/index.css
[class~='ant-col'] {
  background: transparent;
  border: 0;
}
[class~='ant-col'] > div {
  background: #00a0e9;
  height: 120px;
  line-height: 120px;
  font-size: 13px;
}
pre {
  background: #f9f9f9;
  border-radius: 6px;
  font-size: 13px;
  padding: 8px 16px;
}

Slide componentgutterとcolumn数を変化させ、RowとColを定義・描画していきます。

src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Row, Col, Slider } from 'antd';

class App extends React.Component {
  gutters = {};

  colCounts = {};

  constructor() {
    super();
    this.state = {
      gutterKey: 1,
      colCountKey: 2,
    };
    [8, 16, 24, 32, 40, 48].forEach((value, i) => {
      this.gutters[i] = value;
    });
    [2, 3, 4, 6, 8, 12].forEach((value, i) => {
      this.colCounts[i] = value;
    });
  }

  onGutterChange = gutterKey => {
    this.setState({ gutterKey });
  };

  onColCountChange = colCountKey => {
    this.setState({ colCountKey });
  };

  render() {
    const { gutterKey, colCountKey } = this.state;
    const cols = [];
    const colCount = this.colCounts[colCountKey];
    let colCode = '';
    for (let i = 0; i < colCount; i++) {
      cols.push(
        <Col key={i.toString()} span={24 / colCount}>
          <div>Column</div>
        </Col>,
      );
      colCode += `  <Col span={${24 / colCount}} />\n`;
    }
    return (
      <div>
        <div style={{ marginBottom: 16 }}>
          <span style={{ marginRight: 6 }}>Gutter (px): </span>
          <div style={{ width: '50%' }}>
            <Slider
              min={0}
              max={Object.keys(this.gutters).length - 1}
              value={gutterKey}
              onChange={this.onGutterChange}
              marks={this.gutters}
              step={null}
            />
          </div>
          <span style={{ marginRight: 6 }}>Column Count:</span>
          <div style={{ width: '50%' }}>
            <Slider
              min={0}
              max={Object.keys(this.colCounts).length - 1}
              value={colCountKey}
              onChange={this.onColCountChange}
              marks={this.colCounts}
              step={null}
            />
          </div>
        </div>
        <Row gutter={this.gutters[gutterKey]}>{cols}</Row>
        <pre>{`<Row gutter={${this.gutters[gutterKey]}}>\n${colCode}</Row>`}</pre>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('root'));

以下は実行結果です。

Gutter=16, column数=4の場合
image.png

Gutter=48, column数=4の場合
image.png

Gutter=48, column数=8の場合
image.png

2.Layout

Layout Componentはページ全体のLayoutを記述します。

Layout Componentの概要

  • Layout: Header、 Sider、 Content、 Footer または Layout自身のwrpper
  • Header: トップ Layout
  • Sider: sidebar
  • Content: content layout
  • Footer: ボトム Layout

##2-1.シンプルな例

Layoutのシンプルな例です。

src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Layout } from 'antd';

const { Header, Footer, Sider, Content } = Layout;

ReactDOM.render(
  <div>
    <Layout>
      <Sider>Sider</Sider>
      <Layout>
        <Header>Header</Header>
        <Content>Content</Content>
        <Footer>Footer</Footer>
      </Layout>
    </Layout>
  </div>,
  document.getElementById('container'),
);

cssファイルです。

src/index.css
.ant-layout-header,
.ant-layout-footer {
  background: #7dbcea;
  color: #fff;
}
.ant-layout-footer {
  line-height: 1.5;
}
.ant-layout-sider {
  background: #3ba0e9;
  color: #fff;
  line-height: 120px;
}
.ant-layout-content {
  background: rgba(16, 142, 233, 1);
  color: #fff;
  min-height: 120px;
  line-height: 120px;
}

枠組みだけですが、ページ全体がレイアウトされています。

image.png

##2-2. レスポンシブデザイン

Siderはbreakpointを設定することで、レスポンシブデザインをサポートするようになります。windowの横幅がbreakpoint以下になったら、折りたたまれます。

Menu componentが簡単に使えて、Icon componentで様々なアイコンを指定できるのも便利です。他のUIライブラリに比べて、全体的に論理的にスッキリと書けるのではないでしょうか?

src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Layout, Menu, Icon } from 'antd';

const { Header, Content, Footer, Sider } = Layout;

ReactDOM.render(
  <Layout>
    <Sider
      breakpoint="lg"
      collapsedWidth="0"
      onBreakpoint={broken => {
        console.log(broken);
      }}
      onCollapse={(collapsed, type) => {
        console.log(collapsed, type);
      }}
    >
      <div className="logo" />
      <Menu theme="dark" mode="inline" defaultSelectedKeys={['4']}>
        <Menu.Item key="1">
          <Icon type="user" />
          <span className="nav-text">nav 1</span>
        </Menu.Item>
        <Menu.Item key="2">
          <Icon type="video-camera" />
          <span className="nav-text">nav 2</span>
        </Menu.Item>
        <Menu.Item key="3">
          <Icon type="upload" />
          <span className="nav-text">nav 3</span>
        </Menu.Item>
        <Menu.Item key="4">
          <Icon type="user" />
          <span className="nav-text">nav 4</span>
        </Menu.Item>
      </Menu>
    </Sider>
    <Layout>
      <Header style={{ background: '#fff', padding: 0 }} />
      <Content style={{ margin: '24px 16px 0' }}>
        <div style={{ padding: 24, background: '#fff', minHeight: 360 }}>content</div>
      </Content>
      <Footer style={{ textAlign: 'center' }}>Ant Design c2018 Created by Ant UED</Footer>
    </Layout>
  </Layout>,
  document.getElementById('root'),
);

小さいですがCSSです。

src/index.css
.logo {
  height: 32px;
  background: rgba(255, 255, 255, 0.2);
  margin: 16px;
}

初期画面です。
image.png

ブラウザの横幅を縮めると、メニューが折りたたまれます。
image.png

メニューを選択すると、横から飛び出す感じです
image.png

今回は以上です

8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?