diff --git a/docs/examples-dist/tab.vue b/docs/examples-dist/tab.vue
index 962d70a10..fa8534e5d 100644
--- a/docs/examples-dist/tab.vue
+++ b/docs/examples-dist/tab.vue
@@ -4,7 +4,6 @@
   <van-tab title="选项二">内容二</van-tab>
   <van-tab title="选项三">内容三</van-tab>
   <van-tab title="选项四">内容四</van-tab>
-  <van-tab title="选项五">内容五</van-tab>
 </van-tabs>
 
               </example-block><example-block title="基础用法">
@@ -13,7 +12,6 @@
   <van-tab title="选项二">内容二</van-tab>
   <van-tab title="选项三">内容三</van-tab>
   <van-tab title="选项四">内容四</van-tab>
-  <van-tab title="选项五">内容五</van-tab>
 </van-tabs>
 
               </example-block><example-block title="设置切换tab的动画时间">
@@ -23,13 +21,24 @@
   <van-tab title="选项三">内容三</van-tab>
 </van-tabs>
 
-              </example-block><example-block title="禁用tab">
+              </example-block><example-block title="多于4个tab时">
                 <van-tabs>
-  <van-tab title="选项三">内容一</van-tab>
-  <van-tab title="选项二" disabled @disabled="popalert">内容二</van-tab>
+  <van-tab title="选项一">内容一</van-tab>
+  <van-tab title="选项二">内容二</van-tab>
   <van-tab title="选项三">内容三</van-tab>
   <van-tab title="选项四">内容四</van-tab>
   <van-tab title="选项五">内容五</van-tab>
+  <van-tab title="选项六">内容六</van-tab>
+  <van-tab title="选项七">内容七</van-tab>
+  <van-tab title="选项八">内容八</van-tab>
+</van-tabs>
+
+              </example-block><example-block title="禁用tab">
+                <van-tabs>
+  <van-tab title="选项一">内容一</van-tab>
+  <van-tab title="选项二" disabled @disabled="popalert">内容二</van-tab>
+  <van-tab title="选项三">内容三</van-tab>
+  <van-tab title="选项四">内容四</van-tab>
 </van-tabs>
 
 
@@ -40,7 +49,6 @@
   <van-tab title="选项二">内容二</van-tab>
   <van-tab title="选项三">内容三</van-tab>
   <van-tab title="选项四">内容四</van-tab>
-  <van-tab title="选项五">内容五</van-tab>
 </van-tabs>
 
               </example-block><example-block title="自定义样式">
@@ -49,7 +57,6 @@
     <van-tab title="选项二" class="custom-pane">内容二</van-tab>
     <van-tab title="选项三" class="custom-pane">内容三</van-tab>
     <van-tab title="选项四" class="custom-pane">内容四</van-tab>
-    <van-tab title="选项五" class="custom-pane">内容五</van-tab>
 </van-tabs>
 
 
@@ -60,7 +67,6 @@
   <van-tab title="选项二">内容二</van-tab>
   <van-tab title="选项三">内容三</van-tab>
   <van-tab title="选项四">内容四</van-tab>
-  <van-tab title="选项五">内容五</van-tab>
 </van-tabs>
 
 
diff --git a/docs/examples-docs/tab.md b/docs/examples-docs/tab.md
index c8ba3ba11..a9e4e687e 100644
--- a/docs/examples-docs/tab.md
+++ b/docs/examples-docs/tab.md
@@ -97,7 +97,6 @@ export default {
   <van-tab title="选项二">内容二</van-tab>
   <van-tab title="选项三">内容三</van-tab>
   <van-tab title="选项四">内容四</van-tab>
-  <van-tab title="选项五">内容五</van-tab>
 </van-tabs>
 ```
 :::
@@ -113,7 +112,6 @@ export default {
   <van-tab title="选项二">内容二</van-tab>
   <van-tab title="选项三">内容三</van-tab>
   <van-tab title="选项四">内容四</van-tab>
-  <van-tab title="选项五">内容五</van-tab>
 </van-tabs>
 ```
 :::
@@ -132,6 +130,25 @@ export default {
 ```
 :::
 
+#### 多于4个tab时
+
+多于4个tab时,可以横向滚动tab。
+
+:::demo 多于4个tab时
+```html
+<van-tabs>
+  <van-tab title="选项一">内容一</van-tab>
+  <van-tab title="选项二">内容二</van-tab>
+  <van-tab title="选项三">内容三</van-tab>
+  <van-tab title="选项四">内容四</van-tab>
+  <van-tab title="选项五">内容五</van-tab>
+  <van-tab title="选项六">内容六</van-tab>
+  <van-tab title="选项七">内容七</van-tab>
+  <van-tab title="选项八">内容八</van-tab>
+</van-tabs>
+```
+:::
+
 #### 禁用tab
 
 在对应的`van-tab`上设置`disabled`属性即可,如果需要监听禁用事件,可以监听`disabled`事件。
@@ -139,11 +156,10 @@ export default {
 :::demo 禁用tab
 ```html
 <van-tabs>
-  <van-tab title="选项三">内容一</van-tab>
+  <van-tab title="选项一">内容一</van-tab>
   <van-tab title="选项二" disabled @disabled="popalert">内容二</van-tab>
   <van-tab title="选项三">内容三</van-tab>
   <van-tab title="选项四">内容四</van-tab>
-  <van-tab title="选项五">内容五</van-tab>
 </van-tabs>
 
 <script>
@@ -169,7 +185,6 @@ export default {
   <van-tab title="选项二">内容二</van-tab>
   <van-tab title="选项三">内容三</van-tab>
   <van-tab title="选项四">内容四</van-tab>
-  <van-tab title="选项五">内容五</van-tab>
 </van-tabs>
 ```
 :::
@@ -198,7 +213,6 @@ export default {
     <van-tab title="选项二" class="custom-pane">内容二</van-tab>
     <van-tab title="选项三" class="custom-pane">内容三</van-tab>
     <van-tab title="选项四" class="custom-pane">内容四</van-tab>
-    <van-tab title="选项五" class="custom-pane">内容五</van-tab>
 </van-tabs>
 
 <style>
@@ -228,7 +242,6 @@ export default {
   <van-tab title="选项二">内容二</van-tab>
   <van-tab title="选项三">内容三</van-tab>
   <van-tab title="选项四">内容四</van-tab>
-  <van-tab title="选项五">内容五</van-tab>
 </van-tabs>
 
 <script>
diff --git a/packages/dialog/src/dialog.js b/packages/dialog/src/dialog.js
index e3a92c7d8..962d8a950 100644
--- a/packages/dialog/src/dialog.js
+++ b/packages/dialog/src/dialog.js
@@ -32,6 +32,7 @@ const showNextDialog = () => {
     initInstance();
   }
 
+  /* istanbul ignore else */
   if (!instance.value && dialogQueue.length > 0) {
     currentDialog = dialogQueue.shift();
 
diff --git a/packages/image-preview/src/image-preview.js b/packages/image-preview/src/image-preview.js
index 550258380..888693701 100644
--- a/packages/image-preview/src/image-preview.js
+++ b/packages/image-preview/src/image-preview.js
@@ -6,6 +6,7 @@ let instance;
 const ImagePreviewConstructor = Vue.extend(ImagePreview);
 
 const initInstance = () => {
+  /* istanbul ignore if */
   if (Vue.prototype.$isServer) return;
   instance = new ImagePreviewConstructor({
     el: document.createElement('div')
@@ -13,6 +14,7 @@ const initInstance = () => {
 };
 
 var ImagePreviewBox = images => {
+  /* istanbul ignore if */
   if (Vue.prototype.$isServer) return;
   if (!instance) {
     initInstance();
diff --git a/packages/image-preview/src/image-preview.vue b/packages/image-preview/src/image-preview.vue
index 0616ee2cb..570833330 100644
--- a/packages/image-preview/src/image-preview.vue
+++ b/packages/image-preview/src/image-preview.vue
@@ -92,6 +92,7 @@ export default {
     const supportTouch = !Vue.prototype.$isServer && 'ontouchstart' in window;
     const container = this.$refs.previewContainer;
 
+    /* istanbul ignore else */
     if (supportTouch) {
       let touchStartTime;
 
@@ -99,6 +100,7 @@ export default {
         touchStartTime = new Date();
       });
       container.addEventListener('touchend', () => {
+        /* istanbul ignore else */
         if (new Date() - touchStartTime < 1500) {
           this.value = false;
         }
diff --git a/packages/picker/src/picker-column.vue b/packages/picker/src/picker-column.vue
index 01c831061..8dc8e8715 100644
--- a/packages/picker/src/picker-column.vue
+++ b/packages/picker/src/picker-column.vue
@@ -194,6 +194,7 @@ export default {
         },
 
         end: () => {
+          /* istanbul ignore else */
           if (this.isDragging) {
             this.isDragging = false;
 
diff --git a/packages/tab/src/swipe.js b/packages/tab/src/swipe.js
new file mode 100644
index 000000000..5b22acdf4
--- /dev/null
+++ b/packages/tab/src/swipe.js
@@ -0,0 +1,46 @@
+import Vue from 'vue';
+
+let isSwiping = false;
+
+const supportTouch = !Vue.prototype.$isServer && 'ontouchstart' in window;
+
+export default function(element, options) {
+  const moveFn = function(event) {
+    if (options.drag) {
+      options.drag(supportTouch ? event.changedTouches[0] || event.touches[0] : event);
+    }
+  };
+
+  const endFn = function(event) {
+    if (!supportTouch) {
+      document.removeEventListener('mousemove', moveFn);
+      document.removeEventListener('mouseup', endFn);
+    }
+
+    isSwiping = false;
+
+    if (options.end) {
+      options.end(supportTouch ? event.changedTouches[0] || event.touches[0] : event);
+    }
+  };
+
+  element.addEventListener(supportTouch ? 'touchstart' : 'mousedown', function(event) {
+    if (isSwiping) return;
+
+    if (!supportTouch) {
+      document.addEventListener('mousemove', moveFn);
+      document.addEventListener('mouseup', endFn);
+    }
+    isSwiping = true;
+
+    if (options.start) {
+      options.start(supportTouch ? event.changedTouches[0] || event.touches[0] : event);
+    }
+  });
+
+  if (supportTouch) {
+    element.addEventListener('touchmove', moveFn);
+    element.addEventListener('touchend', endFn);
+    element.addEventListener('touchcancel', endFn);
+  }
+};
diff --git a/packages/tab/src/tabs.vue b/packages/tab/src/tabs.vue
index abb91a582..68c325819 100644
--- a/packages/tab/src/tabs.vue
+++ b/packages/tab/src/tabs.vue
@@ -1,8 +1,26 @@
 <template>
   <div class="van-tabs" :class="[`van-tabs--${type}`]">
+    <div class="van-tabs__nav-wrap" v-if="type === 'line' && tabs.length > 4">
+      <div class="van-tabs__swipe" ref="swipe">
+        <div class="van-tabs__nav van-tabs__nav--line">
+          <div class="van-tabs__nav-bar" :style="navBarStyle"></div>
+          <div
+            v-for="(tab, index) in tabs"
+            :key="index"
+            class="van-tab"
+            :class="{'van-tab--active': index === curActive}"
+            ref="tabkey"
+            @click="handleTabClick(index, tab)"
+          >
+            {{ tab.title }}
+          </div>
+        </div>
+      </div>
+    </div>
     <div
+      v-else
       class="van-tabs__nav"
-      :class="[`van-tabs__nav--${this.type}`, `van-tabs--col-${this.tabs.length}`]"
+      :class="[`van-tabs__nav--${this.type}`]"
     >
       <div class="van-tabs__nav-bar" :style="navBarStyle" v-if="type === 'line'"></div>
       <div
@@ -23,6 +41,9 @@
 </template>
 
 <script>
+  import swipe from './swipe';
+  import translateUtil from 'src/utils/transition';
+
   export default {
     name: 'van-tabs',
 
@@ -48,13 +69,21 @@
       return {
         tabs: [],
         isReady: false,
-        curActive: +this.active
+        curActive: +this.active,
+        isSwiping: false
       };
     },
 
     watch: {
       active(val) {
         this.curActive = +val;
+      },
+
+      curActive() {
+        /* istanbul ignore else */
+        if (this.tabs.length > 4) {
+          this.doOnValueChange();
+        }
       }
     },
 
@@ -72,12 +101,38 @@
 
         return {
           width: offsetWidth,
-          transform: `translate3d(${offsetLeft}, 0px, 0px)`,
+          transform: `translate3d(${offsetLeft}, 0, 0)`,
           transitionDuration: `${this.duration}s`
         };
+      },
+      swipeWidth() {
+        return this.$refs.swipe && this.$refs.swipe.getBoundingClientRect().width;
+      },
+      maxTranslate() {
+        /* istanbul ignore if */
+        if (!this.$refs.tabkey) return;
+
+        const lastTab = this.$refs.tabkey[this.tabs.length - 1];
+        const lastTabWidth = lastTab.offsetWidth;
+        const lastTabOffsetLeft = lastTab.offsetLeft;
+
+        return (lastTabOffsetLeft + lastTabWidth) - this.swipeWidth;
       }
     },
 
+    mounted() {
+      // 页面载入完成
+      this.$nextTick(() => {
+        // 可以开始触发在computed中关于nav-bar的css动画
+        this.isReady = true;
+        this.initEvents();
+  
+        if (this.tabs.length > 4) {
+          this.doOnValueChange();
+        }
+      });
+    },
+
     methods: {
       /**
        * tab点击事件
@@ -93,15 +148,67 @@
 
         this.$emit('click', index);
         this.curActive = index;
-      }
-    },
+      },
 
-    mounted() {
-      // 页面载入完成
-      this.$nextTick(() => {
-        // 可以开始触发在computed中关于nav-bar的css动画
-        this.isReady = true;
-      });
+      /**
+       * 将当前value值转换为需要translate的值
+       */
+      value2Translate(value) {
+        /* istanbul ignore if */
+        if (!this.$refs.tabkey) return 0;
+
+        const tab = this.$refs.tabkey[value];
+        const maxTranslate = this.maxTranslate;
+        const tabWidth = tab.offsetWidth;
+        const tabOffsetLeft = tab.offsetLeft;
+        let translate = tabOffsetLeft + (tabWidth * 2.7) - this.swipeWidth;
+        if (translate < 0) {
+          translate = 0;
+        }
+
+        return -1 * (translate > maxTranslate ? maxTranslate : translate);
+      },
+
+      initEvents() {
+        const el = this.$refs.swipe;
+        if (!el) return;
+
+        let swipeState = {};
+
+        swipe(el, {
+          start: event => {
+            swipeState = {
+              start: new Date(),
+              startLeft: event.pageX,
+              startTranslateLeft: translateUtil.getElementTranslate(el).left
+            };
+          },
+
+          drag: event => {
+            this.isSwiping = true;
+
+            swipeState.left = event.pageX;
+            const deltaX = swipeState.left - swipeState.startLeft;
+            const translate = swipeState.startTranslateLeft + deltaX;
+
+            /* istanbul ignore else */
+            if (translate > 0 || (translate * -1) > this.maxTranslate ) return;
+
+            translateUtil.translateElement(el, translate, null);
+          },
+
+          end: () => {
+            this.isSwiping = false;
+          }
+        })
+      },
+
+      doOnValueChange() {
+        const value = +this.curActive;
+        const swipe = this.$refs.swipe;
+
+        translateUtil.translateElement(swipe, this.value2Translate(value), null);
+      }
     }
   };
 </script>
diff --git a/packages/vant-css/src/tab.css b/packages/vant-css/src/tab.css
index 2fe518cfe..f7ace23fe 100644
--- a/packages/vant-css/src/tab.css
+++ b/packages/vant-css/src/tab.css
@@ -5,27 +5,20 @@
   @b tabs {
     position: relative;
 
-    @m col-2 {
-      .van-tab {
-        width: 50%;
-      }
+    @e nav-wrap {
+      overflow: hidden;
     }
 
-    @m col-3 {
-      .van-tab {
-        width: 33.33333333333333%;
-      }
-    }
+    @e swipe {
+      user-select: none;
+      transition: transform ease .3s;
 
-    @m col-4 {
       .van-tab {
-        width: 25%;
+        flex: 0 0 22%;
       }
-    }
 
-    @m col-5 {
-      .van-tab {
-        width: 20%;
+      .van-tabs__nav {
+        overflow: visible;
       }
     }
 
@@ -33,16 +26,15 @@
       overflow: hidden;
       transition: transform .5s cubic-bezier(.645, .045, .355, 1);
       position: relative;
+      display: flex;
 
       @m line {
         height: 44px;
-        background-color: $c-white;
-        &::after {
-          @mixin border-retina (top);
-          @mixin border-retina (bottom);
-        }
-        @b tabs-nav-bar {
-          display: block;
+
+        .van-tab {
+          &::after {
+            @mixin border-retina (top, bottom);
+          }
         }
       }
 
@@ -55,14 +47,16 @@
         overflow: hidden;
 
         .van-tab {
-          color: #666666;
+          color: #666;
           line-height: 28px;
-          border-right: 1px solid #666666;
+          border-right: 1px solid #666;
+
           &:last-child {
             border-right: none;
           }
+
           &.van-tab--active {
-            background-color: #666666;
+            background-color: #666;
             color: $c-white;
           }
         }
@@ -82,13 +76,16 @@
   }
 
   @b tab {
+    position: relative;
     color: $c-black;
+    background-color: $c-white;
     font-size: 14px;
     line-height: 44px;
     box-sizing: border-box;
     cursor: pointer;
     text-align: center;
-    float: left;
+    flex: 1;
+    -webkit-tap-highlight-color: rgba(0,0,0,0);
 
     @m active {
       color: #FF4444;
diff --git a/test/unit/components/more-tabs.vue b/test/unit/components/more-tabs.vue
new file mode 100644
index 000000000..6313f92ca
--- /dev/null
+++ b/test/unit/components/more-tabs.vue
@@ -0,0 +1,28 @@
+<template>
+  <van-tabs :active="active">
+    <van-tab title="选项一">内容一</van-tab>
+    <van-tab title="选项二">内容二</van-tab>
+    <van-tab title="选项三">内容三</van-tab>
+    <van-tab title="选项四">内容四</van-tab>
+    <van-tab title="选项五">内容五</van-tab>
+    <van-tab title="选项六">内容六</van-tab>
+    <van-tab title="选项七">内容七</van-tab>
+    <van-tab title="选项八">内容八</van-tab>
+  </van-tabs>
+</template>
+
+<script>
+import Tab from 'packages/tab';
+import Tabs from 'packages/tabs';
+
+export default {
+  components: {
+    'van-tab': Tab,
+    'van-tabs': Tabs
+  },
+
+  props: {
+    active: [String, Number]
+  }
+};
+</script>
diff --git a/test/unit/components/tabs.vue b/test/unit/components/tabs.vue
index df871ba68..a63a15b0d 100644
--- a/test/unit/components/tabs.vue
+++ b/test/unit/components/tabs.vue
@@ -4,7 +4,6 @@
     <van-tab title="选项二">内容二</van-tab>
     <van-tab title="选项三" disabled>内容三</van-tab>
     <van-tab title="选项四">内容四</van-tab>
-    <van-tab title="选项五">内容五</van-tab>
   </van-tabs>
 </template>
 
diff --git a/test/unit/specs/dialog.spec.js b/test/unit/specs/dialog.spec.js
index 2fad23a13..aa006b88f 100644
--- a/test/unit/specs/dialog.spec.js
+++ b/test/unit/specs/dialog.spec.js
@@ -1,4 +1,5 @@
 import Dialog from 'packages/dialog';
+import Vue from 'vue';
 
 describe('Dialog', () => {
   afterEach(() => {
@@ -51,6 +52,6 @@ describe('Dialog', () => {
       document.querySelector('.van-dialog__cancel').click();
       expect(dialogAction).to.equal('cancel');
       done();
-    }, 50);
+    }, 500);
   });
 });
diff --git a/test/unit/specs/image-preview.spec.js b/test/unit/specs/image-preview.spec.js
index 6475f4b81..d6ad06931 100644
--- a/test/unit/specs/image-preview.spec.js
+++ b/test/unit/specs/image-preview.spec.js
@@ -16,6 +16,7 @@ describe('ImagePreview', () => {
 
   it('create a image preview', (done) => {
     ImagePreview([
+      'https://img.yzcdn.cn/upload_files/2017/03/15/FkubrzN7AgGwLlTeb1E89-T_ZjBg.png',
       'https://img.yzcdn.cn/upload_files/2017/03/14/FmTPs0SeyQaAOSK1rRe1sL8RcwSY.jpeg',
       'https://img.yzcdn.cn/upload_files/2017/03/15/FvexrWlG_WxtCE9Omo5l27n_mAG_.jpeg'
     ]);
@@ -40,6 +41,7 @@ describe('ImagePreview', () => {
     document.body.style.overflow = 'hidden';
 
     ImagePreview([
+      'https://img.yzcdn.cn/upload_files/2017/03/15/FkubrzN7AgGwLlTeb1E89-T_ZjBg.png',
       'https://img.yzcdn.cn/upload_files/2017/03/14/FmTPs0SeyQaAOSK1rRe1sL8RcwSY.jpeg',
       'https://img.yzcdn.cn/upload_files/2017/03/15/FvexrWlG_WxtCE9Omo5l27n_mAG_.jpeg'
     ]);
diff --git a/test/unit/specs/tabs.spec.js b/test/unit/specs/tabs.spec.js
index 377ada337..eb6252a12 100644
--- a/test/unit/specs/tabs.spec.js
+++ b/test/unit/specs/tabs.spec.js
@@ -1,6 +1,7 @@
 import Tabs from 'packages/tabs';
 import { mount } from 'avoriaz';
 import TabsTestComponent from '../components/tabs';
+import MoreTabsTestComponent from '../components/more-tabs';
 
 describe('Tabs', () => {
   let wrapper;
@@ -74,4 +75,75 @@ describe('Tabs', () => {
 
     expect(wrapper.style.transitionDuration != '').to.be.true;
   });
+
+  it('create a tabs greater then 4', (done) => {
+    wrapper = mount(MoreTabsTestComponent, {
+      attachToDocument: true
+    });
+ 
+    wrapper.vm.$nextTick(() => {
+      const nTab = wrapper.find('.van-tab')[4];
+      nTab.trigger('click');
+      done();
+    });
+  });
+
+  it('create a tabs greater then 4 then click last tab', (done) => {
+    wrapper = mount(MoreTabsTestComponent, {
+      attachToDocument: true,
+      propsData: {
+        active: 7
+      }
+    });
+ 
+    wrapper.vm.$nextTick(() => {
+      const nTab = wrapper.find('.van-tab')[6];
+      nTab.trigger('click');
+      done();
+    });
+  });
+
+  it('test swipe', (done) => {
+    wrapper = mount(MoreTabsTestComponent, {
+      attachToDocument: true
+    });
+
+    setTimeout(() => {
+      const nSwipe = wrapper.find('.van-tabs__swipe')[0];
+
+      const eventMouseObject = new window.Event('mousedown');
+      eventMouseObject.pageX = 200;
+      nSwipe.element.dispatchEvent(eventMouseObject);
+
+      const eventTouchObject = new window.Event('touchstart');
+      eventTouchObject.changedTouches = [{ pageX: 200 }];
+      nSwipe.element.dispatchEvent(eventTouchObject);
+    }, 500);
+
+    setTimeout(() => {
+      const nSwipe = wrapper.find('.van-tabs__swipe')[0];
+
+      const eventMouseMoveObject = new window.Event('mousemove');
+      eventMouseMoveObject.pageX = 0;
+      document.dispatchEvent(eventMouseMoveObject);
+
+      const eventObject = new window.Event('touchmove');
+      eventObject.changedTouches = [{ pageX: 0 }];
+      nSwipe.element.dispatchEvent(eventObject);
+
+      // 结束滑动
+      const eventMouseUpObject = new window.Event('mouseup');
+      document.dispatchEvent(eventMouseUpObject);
+      const eventEndObject = new window.Event('touchend');
+      eventEndObject.changedTouches = [{}];
+      nSwipe.element.dispatchEvent(eventEndObject);
+    }, 1000);
+
+    setTimeout(() => {
+      const nItem = wrapper.find('.van-tab')[0];
+      expect(nItem.hasClass('van-tab--active')).to.be.true;
+
+      done();
+    }, 1200);
+  });
 });
diff --git a/test/unit/specs/tag.spec.js b/test/unit/specs/tag.spec.js
index c077e93ab..984beab2e 100644
--- a/test/unit/specs/tag.spec.js
+++ b/test/unit/specs/tag.spec.js
@@ -18,12 +18,4 @@ describe('Tag', () => {
       }
     })
   });
-
-  it('create with wrong typeProps', () => {
-    wrapper = mount(Tag, {
-      propsData: {
-        type: 'wrong'
-      }
-    })
-  });
 });