Taiga UI 5.0 is out!

Surface LAYOUT

Examples Layers GitHub

On this page

General purpose container used in Taiga UI interfaces. Often used in conjunction with Card component.

Behaviors

You can enable hover effects only on devices with pointer:
@media (hover: hover)
    
      
    
    
      <button
    tuiSurface
    type="button"
    class="scale"
>
    Scale
</button>
<button
    tuiSurface
    type="button"
    class="overlay"
>
    Overlay
</button>
<button
    tuiAppearance="primary"
    tuiSurface
    type="button"
    class="highlight"
>
    Highlight
</button>
<button
    tuiSurface
    type="button"
    class="offset"
>
    Offset
</button>
<button
    tuiSurface
    type="button"
    class="background"
>
    Background
</button>
<button
    tuiSurface
    type="button"
    class="shadow"
>
    Shadow
</button>

    
    
      @import '@taiga-ui/styles/utils.less';

.scale {
    @media @tui-mouse {
        &:hover {
            transform: scale(1.15);
        }
    }

    &:active {
        transform: scale(0.95);
    }
}

.overlay {
    &::after {
        opacity: 0;
        background: linear-gradient(
            -45deg,
            #a1a1b3 0.36%,
            #d4d1d8 46.96%,
            #f7fafa 67.14%,
            #d4d1d8 83.19%,
            #a1a1b3 93.03%
        );
    }

    @media @tui-mouse {
        &:hover::after {
            opacity: 0.5;
        }
    }

    &:active::after {
        opacity: 1;
    }
}

.highlight {
    @media @tui-mouse {
        &:hover::before {
            backdrop-filter: brightness(1.1);
        }
    }

    &:active::before {
        backdrop-filter: brightness(0.9);
    }
}

.offset:hover {
    transform: translate3d(0, -0.25rem, 0);
}

.background {
    &::after {
        background: url('/assets/images/not-found.svg') top;
        background-size: 300%;
    }

    &:hover::after {
        transform: scale(1.15);
    }
}

.shadow:hover {
    box-shadow: var(--tui-shadow-small-hover);
}

    

Presets

Note that padding and border-radius are not part of the surface. Take a look at Card component for that.
    
      
    
    
      <button
    tuiAppearance="floating"
    tuiSurface
    type="button"
>
    Floating
</button>
<button
    tuiAppearance="neutral"
    tuiSurface
    type="button"
>
    Neutral
</button>

    
    
      :host {
    display: grid;
    grid-template-columns: repeat(3, 8rem);
    gap: 1rem;
}

[tuiSurface] {
    padding: 1.25rem;
    border-radius: var(--tui-radius-l);
}

    

Blur

Text should have vertical compensation to look properly aligned, either with unequal padding or with negative margin . Typical value is 0.25rem , smaller line-height might require 0.125rem instead.

backdrop-filter

You can use backdrop-filter on tuiSurface element to blur the background behind it.

Never use this mode with shadow
    
      
    
    
      <div
    tuiSurface
    tuiTheme="dark"
    class="blur"
>
    <h2 class="title">backdrop-filter</h2>
    <p>You can use backdrop-filter on tuiSurface element to blur the background behind it.</p>
    Never use this mode with shadow
</div>

    
    
      :host {
    display: block;
    background: url('/assets/images/big-wallpaper.jpg');
    background-size: cover;
    padding: 2rem;
}

.blur {
    backdrop-filter: blur(1rem);
    background: var(--tui-background-neutral-1);
    color: var(--tui-text-primary);
    padding: 1rem 1.25rem;
}

.title {
    margin: 0;
    font: var(--tui-typography-heading-h6);
}

    

Video

Big Buck Bunny

    
      
    
    
      <div
    tuiSurface
    class="surface"
>
    <video
        autoplay
        loop
        playsinline
        tuiSurfaceLayer
        [muted]="true"
    >
        <source
            src="assets/media/bbb.mp4"
            type="video/mp4"
        />
    </video>
    <p>
        <b>Big Buck Bunny</b>
    </p>
</div>

    
    
      .surface {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    block-size: 18rem;
    color: #fff;
    font: var(--tui-typography-body-l);

    &::after {
        background: var(--tui-background-neutral-1);
        box-shadow: inset 0 -7rem 6rem -6rem #000;
        mix-blend-mode: multiply;
    }
}

    

Selectable

    
      
    
    
      @for (_ of '-'.repeat(4); track $index) {
    <label
        tuiSurface
        [style.border-radius.rem]="0.75"
        [style.padding.rem]="1.25"
    >
        Item {{ $index + 1 }}
        <input
            tuiSurfaceLayer
            type="radio"
            [value]="$index"
            [(ngModel)]="value"
        />
        <div
            tuiRipple
            tuiSurfaceLayer
            [style.background-color]="'var(--tui-background-neutral-1)'"
        ></div>
    </label>
}

    
    
      :host {
    display: flex;
    gap: 1rem;
    white-space: nowrap;

    * > {
        flex-shrink: 0;
    }
}

    

Spacing compensation

    
      
    
    
      <button
    tuiAppearance="floating"
    tuiSurface
    type="button"
    class="button"
>
    <span>
        <span class="title">That looks good!</span>
        Apply manual compensation for a more balanced look.
    </span>
    <span
        appearance="accent"
        size="s"
        tuiAvatar="@tui.thumbs-up"
    ></span>
</button>

<button
    tuiAppearance="floating"
    tuiSurface
    type="button"
    class="button bad"
>
    <span>
        <span class="title">This looks bad...</span>
        Use negative margin or reduced padding on specific sides to fix it.
    </span>
    <span
        appearance="accent"
        size="s"
        tuiAvatar="@tui.thumbs-down"
    ></span>
</button>

    
    
      .button {
    display: flex;
    inline-size: 20rem;
    text-align: start;
    gap: 1rem;
    border-radius: 1rem;
    padding: 1rem 1rem 1rem 1.25rem;
    font: var(--tui-typography-body-m);
}

.title {
    display: block;
    font: var(--tui-typography-heading-h6);
    margin-block-end: 0.25rem;
}

.bad {
    margin-block-start: 1rem;
    padding: 1.25rem;
}