diff --git a/components/affix/demo/basic.md b/components/affix/demo/basic.md
index 59c8605560..fc47830b77 100644
--- a/components/affix/demo/basic.md
+++ b/components/affix/demo/basic.md
@@ -14,7 +14,7 @@ title:
The simplest usage.
````jsx
-import { Affix, Button } from 'antd';
+import { Anchor } from 'antd';
ReactDOM.render(
diff --git a/components/anchor/AnchorLink.tsx b/components/anchor/AnchorLink.tsx
new file mode 100644
index 0000000000..ee912467ad
--- /dev/null
+++ b/components/anchor/AnchorLink.tsx
@@ -0,0 +1,21 @@
+import React from 'react';
+
+
+export interface AnchorLinkProps {
+ href: string;
+ onClick: (href: string) => {};
+ active: boolean;
+}
+
+export default class AnchorLink extends React.Component
{
+ onClick = () => {
+ if (this.props.href) {
+ this.props.onClick(this.props.href);
+ }
+ }
+ render() {
+ return
+ {this.props.active ? 'active':null } {this.props.children}
+
;
+ }
+}
\ No newline at end of file
diff --git a/components/anchor/demo/basic.md b/components/anchor/demo/basic.md
new file mode 100644
index 0000000000..8ead991dd9
--- /dev/null
+++ b/components/anchor/demo/basic.md
@@ -0,0 +1,27 @@
+---
+order: 0
+title:
+ zh-CN: 基本
+ en-US: Basic
+---
+
+## zh-CN
+
+最简单的用法。
+
+## en-US
+
+The simplest usage.
+
+```jsx
+
+const { Anchor } = antd;
+
+const { AnchorLink } = Anchor;
+
+ReactDOM.render(
+
+ 锚点1
+
+, mountNode);
+```
\ No newline at end of file
diff --git a/components/anchor/demo/independ.md b/components/anchor/demo/independ.md
new file mode 100644
index 0000000000..fecdcf2d45
--- /dev/null
+++ b/components/anchor/demo/independ.md
@@ -0,0 +1,24 @@
+---
+order: 1
+title:
+ zh-CN: 独立使用 AnchorLink
+ en-US: Independent AnchorLink
+---
+
+## zh-CN
+
+独立使用 AnchorLink
+
+## en-US
+
+Independent AnchorLink
+
+```jsx
+
+const { Anchor } = antd;
+const { AnchorLink } = Anchor;
+
+ReactDOM.render(
+ 锚点1
+, mountNode);
+```
\ No newline at end of file
diff --git a/components/anchor/index.en-US.md b/components/anchor/index.en-US.md
new file mode 100644
index 0000000000..8e082887d9
--- /dev/null
+++ b/components/anchor/index.en-US.md
@@ -0,0 +1,29 @@
+---
+category: Components
+type: Other
+title: Anchor
+---
+
+Make an element sticky to viewport.
+
+## When To Use
+
+When user browses a long web page, some content need to sticky to viewport. It is common for menus and actions.
+
+Please note that Affix should not cover other content in page, especially when the size of viewport is small.
+
+## API
+
+| Property | Description | Type | Default |
+|--------------|-----------------------|----------|--------------|
+| offsetTop | Pixels to offset from top when calculating position of scroll | Number | 0 |
+| offsetBottom | Pixels to offset from bottom when calculating position of scroll | Number | - |
+| onChange | Callback when affix state is changed | Function(affixed) | - |
+
+**Note:** Children of `Affix` can not be `position: absolute`, but you can set `Affix` as `position: absolute`:
+
+```jsx
+
+ ...
+
+```
diff --git a/components/anchor/index.tsx b/components/anchor/index.tsx
new file mode 100644
index 0000000000..2efd17d26a
--- /dev/null
+++ b/components/anchor/index.tsx
@@ -0,0 +1,128 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import addEventListener from 'rc-util/lib/Dom/addEventListener';
+import getScroll from '../_util/getScroll';
+import AnchorLink from './AnchorLink';
+import Affix from '../affix';
+import getRequestAnimationFrame from '../_util/getRequestAnimationFrame';
+
+const reqAnimFrame = getRequestAnimationFrame();
+
+const easeInOutCubic = (t, b, c, d) => {
+ t /= d/2;
+ if (t < 1) return c/2*t*t*t + b;
+ t -= 2;
+ return c/2*(t*t*t + 2) + b;
+};
+
+function getDefaultTarget() {
+ return typeof window !== 'undefined' ?
+ window : null;
+}
+
+function getOffsetTop(element): number {
+ if (!element) {
+ return 0;
+ }
+
+ if (!element.getClientRects().length) {
+ return 0;
+ }
+
+ const rect = element.getBoundingClientRect();
+
+ if ( rect.width || rect.height ) {
+ const doc = element.ownerDocument;
+ const docElem = doc.documentElement;
+ return rect.top + window.pageYOffset - docElem.clientTop;
+ }
+
+ return rect.top;
+}
+
+export interface AnchorProps {
+ target: () => HTMLElement | Window;
+ children: React.ReactNode;
+}
+
+
+export default class Anchor extends React.Component {
+ static AnchorLink = AnchorLink;
+
+ private scrollEvent: any;
+ private sections: Array = [];
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ activeAnchor: null,
+ };
+ }
+ handleScroll = () => {
+ const { target = getDefaultTarget } = this.props;
+ const scrollTop = getScroll(target(), true);
+ let activeAnchor;
+
+ this.sections.forEach(section => {
+ const target = document.querySelector(section);
+ if (target) {
+ const top = target.offsetTop;
+ const bottom = top + target.clientHeight;
+ if ((scrollTop >= top) && (scrollTop <= bottom)) {
+ activeAnchor = section;
+ }
+ }
+ });
+
+ if (activeAnchor) {
+ this.setState({
+ activeAnchor,
+ });
+ }
+ }
+
+ componentDidMount() {
+ this.handleScroll();
+ this.scrollEvent = addEventListener((this.props.target || getDefaultTarget)(), 'scroll', this.handleScroll);
+ }
+
+ componentWillUnmount() {
+ if (this.scrollEvent) {
+ this.scrollEvent.remove();
+ }
+ }
+
+ scrollTo = (href) => {
+ const { target = getDefaultTarget } = this.props;
+ const scrollTop = getScroll(target(), true);
+ const offsetTop = getOffsetTop(document.querySelector(href));
+ const startTime = Date.now();
+ const frameFunc = () => {
+ const timestamp = Date.now();
+ const time = timestamp - startTime;
+ document.body.scrollTop = easeInOutCubic(time, scrollTop, offsetTop, 450);
+ if (time < 450) {
+ reqAnimFrame(frameFunc);
+ }
+ };
+ reqAnimFrame(frameFunc);
+ }
+
+ renderAnchorLink = (child) => {
+ const { href } = child.props;
+ if (href) {
+ if (this.sections.indexOf(href) === -1) {
+ this.sections.push(href);
+ }
+ return React.cloneElement(child, { onClick: this.scrollTo, active: this.state.activeAnchor === href });
+ }
+ return child;
+ }
+
+ render() {
+ return
+ {React.Children.map(this.props.children, this.renderAnchorLink)}
+ ;
+ }
+}
+
diff --git a/components/anchor/index.zh-CN.md b/components/anchor/index.zh-CN.md
new file mode 100644
index 0000000000..9912071da8
--- /dev/null
+++ b/components/anchor/index.zh-CN.md
@@ -0,0 +1,31 @@
+---
+category: Components
+subtitle: 锚点
+type: Other
+title: Anchor
+---
+
+将页面元素钉在可视范围。
+
+## 何时使用
+
+当内容区域比较长,需要滚动页面时,这部分内容对应的操作或者导航需要在滚动范围内始终展现。常用于侧边菜单和按钮组合。
+
+页面可视范围过小时,慎用此功能以免遮挡页面内容。
+
+## API
+
+| 成员 | 说明 | 类型 | 默认值 |
+|-------------|----------------|--------------------|--------------|
+| offsetTop | 距离窗口顶部达到指定偏移量后触发 | Number | |
+| offsetBottom | 距离窗口底部达到指定偏移量后触发 | Number | |
+| target | 设置 `Affix` 需要监听其滚动事件的元素,值为一个返回对应 DOM 元素的函数 | Function | () => window |
+| onChange | 固定状态改变时触发的回调函数 | Function(affixed) | 无 |
+
+**注意:**`Affix` 内的元素不要使用绝对定位,如需要绝对定位的效果,可以直接设置 `Affix` 为绝对定位:
+
+```jsx
+
+ ...
+
+```
diff --git a/components/anchor/style/index.less b/components/anchor/style/index.less
new file mode 100644
index 0000000000..34b46f360b
--- /dev/null
+++ b/components/anchor/style/index.less
@@ -0,0 +1,5 @@
+@import "../../style/themes/default";
+
+.@{ant-prefix}-anchor {
+ color: red;
+}
diff --git a/components/anchor/style/index.tsx b/components/anchor/style/index.tsx
new file mode 100644
index 0000000000..3a3ab0de59
--- /dev/null
+++ b/components/anchor/style/index.tsx
@@ -0,0 +1,2 @@
+import '../../style/index.less';
+import './index.less';
diff --git a/components/anchor/style/index.zh-CN.md b/components/anchor/style/index.zh-CN.md
new file mode 100644
index 0000000000..531bed8ddd
--- /dev/null
+++ b/components/anchor/style/index.zh-CN.md
@@ -0,0 +1,31 @@
+---
+category: Components
+subtitle: 固钉
+type: Other
+title: Affix
+---
+
+将页面元素钉在可视范围。
+
+## 何时使用
+
+当内容区域比较长,需要滚动页面时,这部分内容对应的操作或者导航需要在滚动范围内始终展现。常用于侧边菜单和按钮组合。
+
+页面可视范围过小时,慎用此功能以免遮挡页面内容。
+
+## API
+
+| 成员 | 说明 | 类型 | 默认值 |
+|-------------|----------------|--------------------|--------------|
+| offsetTop | 距离窗口顶部达到指定偏移量后触发 | Number | |
+| offsetBottom | 距离窗口底部达到指定偏移量后触发 | Number | |
+| target | 设置 `Affix` 需要监听其滚动事件的元素,值为一个返回对应 DOM 元素的函数 | Function | () => window |
+| onChange | 固定状态改变时触发的回调函数 | Function(affixed) | 无 |
+
+**注意:**`Affix` 内的元素不要使用绝对定位,如需要绝对定位的效果,可以直接设置 `Affix` 为绝对定位:
+
+```jsx
+
+ ...
+
+```
diff --git a/components/index.tsx b/components/index.tsx
index 6dca06cac8..c537d6169c 100644
--- a/components/index.tsx
+++ b/components/index.tsx
@@ -9,6 +9,8 @@ please use https://www.npmjs.com/package/babel-plugin-import to reduce app bundl
export { default as Affix } from './affix';
+export { default as Anchor } from './anchor';
+
export { default as AutoComplete } from './auto-complete';
export { default as Alert } from './alert';
@@ -101,4 +103,4 @@ export { default as Tooltip } from './tooltip';
export { default as Mention } from './mention';
-export { default as Upload } from './upload';
+export { default as Upload } from './upload';
\ No newline at end of file