diff --git a/config/hooks.ts b/config/hooks.ts
index 26ffff428a..04f70b18ef 100644
--- a/config/hooks.ts
+++ b/config/hooks.ts
@@ -101,6 +101,7 @@ export const menus = [
'useScroll',
'useSize',
'useFocusWithin',
+ 'useStickyFixed',
],
},
{
diff --git a/packages/hooks/src/index.ts b/packages/hooks/src/index.ts
index 55c7232b0d..c84d76f81b 100644
--- a/packages/hooks/src/index.ts
+++ b/packages/hooks/src/index.ts
@@ -76,6 +76,7 @@ import useWebSocket from './useWebSocket';
import useWhyDidYouUpdate from './useWhyDidYouUpdate';
import useMutationObserver from './useMutationObserver';
import useTheme from './useTheme';
+import useStickyFixed from './useStickyFixed';
export {
useRequest,
@@ -158,4 +159,5 @@ export {
useResetState,
useMutationObserver,
useTheme,
+ useStickyFixed,
};
diff --git a/packages/hooks/src/useStickyFixed/demo/demo1.tsx b/packages/hooks/src/useStickyFixed/demo/demo1.tsx
new file mode 100644
index 0000000000..048f193c38
--- /dev/null
+++ b/packages/hooks/src/useStickyFixed/demo/demo1.tsx
@@ -0,0 +1,47 @@
+/**
+ * title: Basic usage
+ * desc: Need to input the sticky positioning element target and the rolling container scrollTarget, ScrollTarget defaults to document
+ *
+ * title.zh-CN: 基础用法
+ * desc.zh-CN: 需要传入粘性定位元素target和滚动容器scrollTarget, scrollTarget默认为document
+ *
+ */
+
+import React, { useRef, useState } from 'react';
+import { useStickyFixed } from 'ahooks';
+
+export default () => {
+ const [topV, setTopV] = useState(0);
+
+ const targetRef = useRef(null);
+ const scrollTargetRef = useRef(null);
+
+ const [isFixed] = useStickyFixed(targetRef, { scrollTarget: scrollTargetRef });
+
+ const fixedStyle = { background: 'pink' };
+
+ return (
+ <>
+
+ top: setTopV(Number(e.target.value))} />
+
+
+
+
top content
+
+ sticky dom
+
+
bottom content
+
+
+ isFixed :{`${isFixed}`}
+ >
+ );
+};
diff --git a/packages/hooks/src/useStickyFixed/demo/demo2.tsx b/packages/hooks/src/useStickyFixed/demo/demo2.tsx
new file mode 100644
index 0000000000..9b11821d74
--- /dev/null
+++ b/packages/hooks/src/useStickyFixed/demo/demo2.tsx
@@ -0,0 +1,46 @@
+/**
+ * title: Pass in DOM element
+ * desc: Pass in a function that returns the DOM element.
+ *
+ * title.zh-CN: 传入 DOM 元素
+ * desc.zh-CN: 传入 function 并返回一个 dom 元素。
+ *
+ */
+
+import React, { useState } from 'react';
+import { useStickyFixed } from 'ahooks';
+
+export default () => {
+ const [topV, setTopV] = useState(0);
+
+ const [isFixed] = useStickyFixed(() => document.getElementById('target'), {
+ scrollTarget: () => document.getElementById('scrollTarget'),
+ });
+
+ const fixedStyle = { background: 'pink' };
+
+ return (
+ <>
+
+ top: setTopV(Number(e.target.value))} />
+
+
+
+
+ isFixed :{`${isFixed}`}
+ >
+ );
+};
diff --git a/packages/hooks/src/useStickyFixed/index.en-US.md b/packages/hooks/src/useStickyFixed/index.en-US.md
new file mode 100644
index 0000000000..6c1dc711d4
--- /dev/null
+++ b/packages/hooks/src/useStickyFixed/index.en-US.md
@@ -0,0 +1,47 @@
+---
+nav:
+ path: /hooks
+---
+
+# useStickyFixed
+
+Observe whether the element of 'position: sticky' is in a fixed suction state
+
+## Examples
+
+### Basic usage
+
+
+
+### Pass in DOM element
+
+
+
+## API
+
+```typescript
+const [isFixed] = useStickyFixed(targetRef, { scrollTarget });
+```
+
+### Params
+
+| Property | Description | Type | Default |
+| -------- | ---------------------------------------- | ----------------------------------------------------------- | ------- |
+| target | `position: sticky` 's Dom element or ref | `() => Element` \| `Element` \| `MutableRefObject` | - |
+| options | More config | `Options` | - |
+
+### Options
+
+| Property | Description | Type | Default |
+| ------------- | --------------------------------------------------- | ----------------------------------------------------------- | ------- |
+| scrollTarget | The element or ref of the DOM in the scrolling area | `() => Element` \| `Element` \| `MutableRefObject` | document|
+
+
+### Result
+
+| Property | Description | Type |
+| ------------- | ------------------------------------------------------ | --------- |
+| isFixed | Is the `position: sticky` 's Dom in the 'fixed' state | `boolean` |
+
+
+
diff --git a/packages/hooks/src/useStickyFixed/index.ts b/packages/hooks/src/useStickyFixed/index.ts
new file mode 100644
index 0000000000..e690ae1a98
--- /dev/null
+++ b/packages/hooks/src/useStickyFixed/index.ts
@@ -0,0 +1,48 @@
+import { useRef } from 'react';
+import { getTargetElement, type BasicTarget } from '../utils/domTarget';
+import useEffectWithTarget from '../utils/useEffectWithTarget';
+import useRafState from '../useRafState';
+
+function useStickyFixed(
+ target: BasicTarget,
+ options?: {
+ scrollTarget?: BasicTarget;
+ },
+): [boolean] {
+ const { scrollTarget } = options || {};
+
+ const [state, setState] = useRafState(false);
+ const lastTopRef = useRef(0);
+
+ useEffectWithTarget(
+ () => {
+ const scrollElement = getTargetElement(scrollTarget, document);
+ if (!scrollElement) {
+ return;
+ }
+
+ const stickyElement = getTargetElement(target);
+ if (!stickyElement) {
+ return;
+ }
+
+ const handleScroll = () => {
+ const rect = stickyElement.getBoundingClientRect();
+ const currentTop = rect.top;
+ const lastTop = lastTopRef.current;
+ setState(currentTop === lastTop);
+ lastTopRef.current = currentTop;
+ };
+
+ scrollElement.addEventListener('scroll', handleScroll);
+ return () => {
+ scrollElement.removeEventListener('scroll', handleScroll);
+ };
+ },
+ [],
+ target,
+ );
+
+ return [state];
+}
+export default useStickyFixed;
diff --git a/packages/hooks/src/useStickyFixed/index.zh-CN.md b/packages/hooks/src/useStickyFixed/index.zh-CN.md
new file mode 100644
index 0000000000..c80f7672e9
--- /dev/null
+++ b/packages/hooks/src/useStickyFixed/index.zh-CN.md
@@ -0,0 +1,43 @@
+---
+nav:
+ path: /hooks
+---
+
+# useStickyFixed
+
+观察粘性定位(`position: sticky`)的元素,是否处于吸顶固定状态
+
+## 代码演示
+
+### 基础用法
+
+
+
+### 传入 DOM 元素
+
+
+
+## API
+
+```typescript
+const [isFixed] = useStickyFixed(targetRef, { scrollTarget });
+```
+
+### Params
+
+| 参数 | 说明 | 类型 | 默认值 |
+| ------- | -------------------------------- | ---------------------------------------------------------- | ------ |
+| target | 粘性定位的 DOM 节点或者 Ref 对象 | `Element` \|`() => Element` \| `MutableRefObject` | - |
+| options | 额外的配置项 | `Options` | - |
+
+### Options
+
+| 参数 | 说明 | 类型 | 默认值 |
+| ------------ | -------------------------------- | ------------------------------------------------------------------------ | -------- |
+| scrollTarget | 滚动区域的 DOM 节点或者 Ref 对象 | `Element` \| `Document` \|`() => Element` \| `MutableRefObject` | document |
+
+### Result
+
+| 参数 | 说明 | 类型 |
+| ------- | --------------------------------- | --------- |
+| isFixed | 粘性定位元素是否处于 `fixed` 状态 | `boolean` |