Defining the taxonomy of a horizontal layout and what you should be concerned with when designing content horizontally. Here lies an opinionated design guideline for designing horizontal content.

Vue Horizontal



  • Item, card or content; there are many names for it. It's where you display the items horizontally.
  • Content should be equally sized, same height, same width.
  • Content should be sized responsive to the viewport.
  • Content should snap to start, end or center after scrolling.
  • Content should have a background different to the container with at least 12px padding.


  • The horizontal gap between items, should be at least 16px wide.
    • margin-right should be used because content should start from 0. This is also due to firefox compatibility issues, as it does not snap to 0 on screen load. (Instead of margin: 0 8px it should be margin-right: 16px)
    • scroll-padding-left: 24px can be used to change the snap to position area, especially useful add padding to the side of a 100vw vue-horizontal.
  • The vertical gap should appear if:
    • Scrollbar is enabled.
    • Shadow are enabled for your content.
    • Basically anything that can cause clipping. Margin will add space so that the effects is not clipped.


  • Scrollbar indicate to the users that the items can be horizontally scrolled.
    • Navigation button is used in Vue Horizontal to indicate just that.
  • The opinionated view is to have scrollbar disabled by default, due to the poor user experience of dragging the bar.
    • For mouse users, scrolling should be done with navigation button.
    • For trackpad users, they can use touch scrolling.
    • For mobile touch screen user, they can use touch scrolling.
  • Alternative to scrollbar to seek content.
  • Should only appear if there are content to be scrolled.
  • Should snap to item after scrolling.
  • Should scroll smoothly to indicate to touch screen and trackpad users they can touch scroll.
  • Should not block content.
    • Should be relative to the content height, smaller content height equals to smaller button.
    • Thus, for the benefit of mobile users, it should be hidden if view port width is low.
    • For mobile users peeking should be used to indicate that users can touch scroll to next.


  • Alternative to scrollbar and navigation to indicate to the users that the items can be horizontally scrolled.
  • Indicate to mobile users you can touch scroll to seek to the next item.
    • Should only appear on mobile devices; screen with <640 viewport width.
  • Peek 8px of items on the left and right. Peeking should only appear if there are actual items on the left or right.
  • Vue Horizontal must be 100vw for a seamless edge to edge experience.
    • scroll-padding-left: 24px can be used to snap correctly.

Peeking Example

  • Accomplished though the use of first-child last-child to set different padding and scroll padding condition.
  • There are also many ways other way to accomplish this.

Assuming 24px container padding/margin with 8px peeking 16px gap. (8+16 = 24)

Peeking.vueimport=design/design-peeking.vue padding=0
      <p>Assuming 24px container padding/margin with 8px peeking 16px gap. (8+16 = 24)</p>

    <vue-horizontal :button="false" class="horizontal">
      <section v-for="i in [0,1,2]" :key="i">

<!-- Peeking Style -->
<style scoped>
.horizontal >>> .v-hl-container {
  scroll-padding-left: 16px;
  scroll-padding-right: 16px;

section {
  width: calc(100% - (16px + 16px));
  padding: 16px 8px;

section:first-child {
  width: calc(100% - (16px));
  padding-left: 24px;

section:last-child {
  width: calc(100% - (16px));
  padding-right: 24px;

<!-- Design Style -->
<style scoped>
section:nth-child(2) {
  background: green;

section > div {
  background: black;
  height: 100px;
  border-radius: 3px;

main {
  margin: 24px 0;
  background: purple;

header {
  margin: 0 24px;
  background: white;

.horizontal {
  background: orange;