Principles

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
ITEM
ITEM
ITEM
ITEM
ITEM
ITEM
ITEM
ITEM
ITEM
ITEM

Item

ITEM
  • 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.

Margin

GAP
  • 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

BAR
  • 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.
NAV
  • 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.

Peeking

PEEK
  • 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
<template>
  <main>
    <header>
      <p>Assuming 24px container padding/margin with 8px peeking 16px gap. (8+16 = 24)</p>
    </header>

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

<!-- 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;
}
</style>

<!-- 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;
}
</style>