Skip to content

Layout

Description

To make it easier to build application layout and form-views in line with defined design sketches, there are a number of components for layout.

Wrappers

  • Card is a block section element showing the white box with rounded gray borders, adding spacing automatically.

  • Stack is an outer block element for wrapping content to get the correct layout and spacing between region and region headings.

Flex layout

  • Flex.Container is a building block for CSS flexbox based layout of contents and components.

    • <Flex.Vertical> can be used as an alias instead of the property direction="vertical".
    • <Flex.Horizontal> can be used as an alias instead of the property direction="horizontal".
  • Flex.Item is a building block for CSS flexbox based layout of contents and components.

Grid layout

  • GridContainer is a layout system for CSS grid based layout of contents.

  • GridItem is a layout system for CSS grid based layout of contents.

Columns

UX designers are using a 12 column system, along with a 4 and 6 column system, during their design processes.

What are the differences between Flex and Grid?

Both to support different sizing of items on different media breakpoints.

Flex

Uses CSS flexbox.

  • Best suited for Forms layout.
  • Can either stack vertically or horizontally.
  • Can be used with any kind of children.
  • Even distribution of space.
  • Keeps order of items like they where given in the DOM structure.
  • Items can be sized in percentage.
  • When a size (percentage) is given, they stack horizontally.
import { Flex } from '@dnb/eufemia'
render(
<Flex.Container>
<Flex.Item>content</Flex.Item>
<OtherComponent>content</OtherComponent>
</Flex.Container>,
)

Grid

Uses CSS grid.

  • Best suited for applications with a column based layout.
  • Columns do change between 4, 6 and 12 on the given size (media query) of the browser or screen size.
  • GridContainer depends on GridItem (Item).
  • Items do span from column a to b.
  • Items can have different order in opposition from what's given in the DOM structure.
import { Layout } from '@dnb/eufemia'
render(
<Layout.GridContainer>
<Layout.GridItem>content</Layout.GridItem>
<Layout.GridItem>content</Layout.GridItem>
</Layout.GridContainer>,
)

Units and responsiveness

Please – use rem instead of px for all of your custom CSS, and make sure;

  • you always use the nearest half rem value, like 0.5rem, 1rem or 1.5rem and so forth.
  • you always get a total computed height within the grid.

This results in maintaining the integrity of the 8px base grid.

Exceptions

There are exceptions for when you define a "minimum" of an area, such as min-width. Because it will increase in size when a larger browser font-size is used. In that case, user px as your sizing unit.

Smaller Units

Sometimes you may need a compensation of only a few pixels. Heres how to calculate the correct rem values:

  • 1px = 1/16x1 = 0.0625rem
  • 2px = 1/16x2 = 0.125rem
  • And so on ...

Demos

Used in forms

Profile

Name

More information

Code Editor
<Flex.Stack>
  <Form.MainHeading>Profile</Form.MainHeading>

  <Card stack>
    <Form.SubHeading>Name</Form.SubHeading>

    <Field.String label="Fornavn" value="John" />
    <Field.String label="Etternavn" value="Smith" />
  </Card>

  <Card stack>
    <Form.SubHeading>More information</Form.SubHeading>

    <Field.NationalIdentityNumber value="20058512345" />
    <Field.Email value="john@smith.email" />
    <Field.PhoneNumber value="+47 98765432" />
  </Card>
</Flex.Stack>

Responsive forms

Label

Responsive GridContainer

Item A
Item B
Item C
Item D
Code Editor
<Layout.GridContainer rowGap columnGap>
  <Layout.GridItem
    span={{
      small: [1, 2],
      medium: [1, 3],
      large: [1, 12],
    }}
    style={colors[0]}
    element={TestElement}
  >
    Item A
  </Layout.GridItem>

  <Layout.GridItem
    span={{
      small: [3, 4],
      medium: [4, 6],
      large: [1, 4],
    }}
    style={colors[1]}
    element={TestElement}
  >
    Item B
  </Layout.GridItem>

  <Layout.GridItem
    span={{
      small: [2, 3],
      medium: [4, 6],
      large: [5, 8],
    }}
    style={colors[2]}
    element={TestElement}
  >
    Item C
  </Layout.GridItem>

  <Layout.GridItem
    span={{
      small: [1, 4],
      medium: [4, 6],
      large: [9, 12],
    }}
    style={colors[3]}
    element={TestElement}
  >
    Item D
  </Layout.GridItem>
</Layout.GridContainer>

Responsive Flex.Item

With the default sizeCount of 12 parts.

FlexItem (8)
FlexItem (4)
FlexItem (small: 8, medium: 4)
FlexItem (small: 4, medium: 8)
Code Editor
<Flex.Container>
  <Flex.Item size={8}>
    <TestElement style={colors[0]}>FlexItem (8)</TestElement>
  </Flex.Item>
  <Flex.Item size={4}>
    <TestElement style={colors[1]}>FlexItem (4)</TestElement>
  </Flex.Item>
  <Flex.Item
    size={{
      small: 12,
      medium: 4,
    }}
  >
    <TestElement style={colors[2]}>
      FlexItem (small: 8, medium: 4)
    </TestElement>
  </Flex.Item>
  <Flex.Item
    size={{
      small: 12,
      medium: 8,
    }}
  >
    <TestElement style={colors[3]}>
      FlexItem (small: 4, medium: 8)
    </TestElement>
  </Flex.Item>
</Flex.Container>

Customized Flex.Item sizes

With a custom amount of 4 parts (sizeCount) as well as custom breakpoints and media queries.

FlexItem
FlexItem
FlexItem
FlexItem
Code Editor
const breakpoints = {
  ...defaultBreakpoints,
  xsmall: '30em',
}
const queries = {
  ...defaultQueries,
  xsmall: {
    min: 0,
    max: 'xsmall',
  },
  small: {
    min: 'xsmall',
    max: 'small',
  },
}
const CustomMediaQuery = styled.div`
  display: flex;
  flex-direction: column;
  .dnb-flex-container[data-media-key='xsmall'] .dnb-flex-item--responsive {
    --size: var(--xsmall);
  }
`
render(
  <CustomMediaQuery>
    <Flex.Container
      direction="horizontal"
      sizeCount={4}
      breakpoints={breakpoints}
      queries={queries}
    >
      <Flex.Item
        size={{
          small: 2,
          medium: 3,
          large: 1,
        }}
      >
        <TestElement style={colors[0]}>FlexItem</TestElement>
      </Flex.Item>
      <Flex.Item
        size={{
          small: 2,
          medium: 1,
          large: 2,
        }}
      >
        <TestElement style={colors[1]}>FlexItem</TestElement>
      </Flex.Item>
      <Flex.Item
        size={{
          xsmall: 4,
          small: 2,
          medium: 1,
          large: 1,
        }}
      >
        <TestElement style={colors[2]}>FlexItem</TestElement>
      </Flex.Item>
      <Flex.Item
        size={{
          xsmall: 4,
          small: 2,
          medium: 3,
          large: 4,
        }}
      >
        <TestElement style={colors[3]}>FlexItem</TestElement>
      </Flex.Item>
    </Flex.Container>
  </CustomMediaQuery>,
)