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.

import { Layout } from '@dnb/eufemia'
render(
<Layout.FlexContainer>
<Layout.FlexItem>content</Layout.FlexItem>
<Layout.FlexItem>content</Layout.FlexItem>
</Layout.FlexContainer>,
)

Layout helpers

Flex layout

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

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

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.

Headings

  • MainHeading is a standardized main heading for sections, ensuring default layout, spacing etc.

  • SubHeading is a standardized sub heading for sections, ensuring default layout, spacing etc.

You may use the Eufemia Layout component for your application layouts and form-views.

Or you may just use CSS Flexbox or CSS Grid. But please, do not use third-party layout libraries.

It is your responsibility to ensure 100% consistency and compatibility.

Grid

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

There are plans to implement support for this in the future.

Responsiveness

In short, only use rem for layouts and spacing 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.

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
<Layout.Stack>
  <Form.MainHeading>Profile</Form.MainHeading>

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

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

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

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

Responsive forms

Label

Responsive FlexItem

With the default sizeCount of 12 parts.

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

Customized FlexItem 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-layout-flex-container[data-media-key='xsmall']
    .dnb-layout-flex-item--responsive {
    --size: var(--xsmall);
  }
`
render(
  <CustomMediaQuery>
    <Layout.FlexContainer
      direction="horizontal"
      sizeCount={4}
      breakpoints={breakpoints}
      queries={queries}
    >
      <Layout.FlexItem
        size={{
          small: 2,
          medium: 3,
          large: 1,
        }}
      >
        <TestElement style={colors[0]}>FlexItem</TestElement>
      </Layout.FlexItem>
      <Layout.FlexItem
        size={{
          small: 2,
          medium: 1,
          large: 2,
        }}
      >
        <TestElement style={colors[1]}>FlexItem</TestElement>
      </Layout.FlexItem>
      <Layout.FlexItem
        size={{
          xsmall: 4,
          small: 2,
          medium: 1,
          large: 1,
        }}
      >
        <TestElement style={colors[2]}>FlexItem</TestElement>
      </Layout.FlexItem>
      <Layout.FlexItem
        size={{
          xsmall: 4,
          small: 2,
          medium: 3,
          large: 4,
        }}
      >
        <TestElement style={colors[3]}>FlexItem</TestElement>
      </Layout.FlexItem>
    </Layout.FlexContainer>
  </CustomMediaQuery>,
)