Affix

Wrap Affix around another component to make it stick the viewport.

When To Use#

On longer web pages, it's helpful to stick component into the viewport. This is common for menus and actions.

Please note that Affix should not cover other content on the page, especially when the size of the viewport is small.

Examples


The simplest usage.

expand codeexpand code
import { Affix, Button } from 'infrad';
import React, { useState } from 'react';

const App: React.FC = () => {
  const [top, setTop] = useState(10);
  const [bottom, setBottom] = useState(10);

  return (
    <>
      <Affix offsetTop={top}>
        <Button type="primary" onClick={() => setTop(top + 10)}>
          Affix top
        </Button>
      </Affix>
      <br />
      <Affix offsetBottom={bottom}>
        <Button type="primary" onClick={() => setBottom(bottom + 10)}>
          Affix bottom
        </Button>
      </Affix>
    </>
  );
};

export default App;

Set a target for 'Affix', which is listen to scroll event of target element (default is window).

expand codeexpand code
import { Affix, Button } from 'infrad';
import React, { useState } from 'react';

const App: React.FC = () => {
  const [container, setContainer] = useState<HTMLDivElement | null>(null);

  return (
    <div className="scrollable-container" ref={setContainer}>
      <div className="background">
        <Affix target={() => container}>
          <Button type="primary">Fixed at the top of container</Button>
        </Affix>
      </div>
    </div>
  );
};

export default App;

Callback with affixed state.

expand codeexpand code
import { Affix, Button } from 'infrad';
import React from 'react';

const App: React.FC = () => (
  <Affix offsetTop={120} onChange={affixed => console.log(affixed)}>
    <Button>120px to affix top</Button>
  </Affix>
);

export default App;

API#

PropertyDescriptionTypeDefault
offsetBottomOffset from the bottom of the viewport (in pixels)number-
offsetTopOffset from the top of the viewport (in pixels)number0
targetSpecifies the scrollable area DOM node() => HTMLElement() => window
onChangeCallback for when Affix state is changed(affixed?: boolean) => void-

Note: Children of Affix must not have the property position: absolute, but you can set position: absolute on Affix itself:

<Affix style={{ position: 'absolute', top: y, left: x }}>...</Affix>

FAQ#

When binding container with target in Affix, elements sometimes move out of the container.#

We only listen to container scroll events for performance consideration. You can add custom listeners if you still want to: https://codesandbox.io/s/2xyj5zr85p

Related issues:#3938 #5642 #16120

When Affix is ​​used in a horizontal scroll container, the position of the element left is incorrect.#

Affix is ​​generally only applicable to areas with one-way scrolling, and only supports usage in vertical scrolling containers. If you want to use it in a horizontal container, you can consider implementing with the native position: sticky property.

Related issues:#29108