Git Product home page Git Product logo

react-sticky's People

Contributors

4lejandrito avatar aarongoin avatar aaronjensen avatar amsardesai avatar bowlingx avatar chiefjester avatar daviferreira avatar dbarbalato avatar gitadept avatar glifchits avatar handtrix avatar ignatiusreza avatar jjjjw avatar joshcarr avatar krzysiek1507 avatar lauriejones avatar maecapozzi avatar michaeldeboey avatar nhardy avatar nvartolomei avatar oddsund avatar papercuptech avatar pfulop avatar pvande avatar rikukissa avatar theadam avatar timdoes avatar vcarl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-sticky's Issues

className lag

When component mounts, div element does not have className passed as props, it happens only after first tick. Because of that, sticky block changes after page load.

As a solution, I am setting className: this.props.className in getInitialState()

Proposal: Empty div with Height to prevent jank when sticking/unsticking

Problem:

  • The child nodes of <Sticky> component are switched to position: fixed
  • They go out of their current position and stick to the top
  • Other divs below them suddenly jump into the now empty space that these child nodes occupied
  • This causes a jank

Proposal:

  • When rendering <Sticky>, add a hidden, empty faux <div> tag
  • Before sticky gets activated, set height of this faux div as the current height of Sticky container
    • For e.g. If Sticky children had 100px height, just before sticky gets activated the faux div gets height set as 100px
  • After the faux div height is set, the Sticky child nodes now get position: fixed
  • Now there is no jank. Other divs below the Sticky container don't jump to the top because the faux div now occupies that space
  • When Sticky gets disabled, simply set height of faux div to 0

When Sticky is not active:

<div> <!-- sticky component -->
  <div> {sticky children} </div>
  <div class="sticky-faux" style="height: 0px"></div>
</div>
<div> {other divs ...} </div>

When Sticky is active:

Let's say height of the children was 100px,

<div> <!-- sticky component -->
  <div class="sticky" style="position: fixed; ..."> {sticky children} </div>
  <div class="sticky-faux" style="height: 100px"></div>
</div>
<div> {other divs ...} </div>

If you think this is fine, I can raise a PR with the changes. So how about this?

feature request: add parent container option

I want my sticky nav to retain the width of its containing element. I also only want this to render on the client. How about adding an option that defines the container:

<Sticky container="some-wrapper">

Then check for the DOM and create the styles based on the container:

import {canUseDOM} from 'exenv';
...
    const styles = {
      position: 'fixed',
      top: 0,
      left: 0,
      right: 0,
      zIndex: 1000,
      width: '100%'
    }

    if (canUseDOM && this.props.container) {
      const container = document.getElementById(this.props.container);
      const boundingClientRect = container.getBoundingClientRect();
      styles.left = boundingClientRect.left;
      styles.right = boundingClientRect.right;
      styles.width = container.clientWidth + 'px';
    }

Sticky footer ?

I wondered if it possible to use this library to make a sticky 'footer', i.e. an element fixed at the bottom until the user scrolls down the page to the "original" place, above a footer for example ?

Custom element for StickyContainer

I have a case where I need the sticky container to be a section, but don't want to have an extra wrapper around the content. Would it make sense to allow passing in a custom html tag as a prop?

shouldComponentUpdate should check children

Seemingly the fact that shouldComponentUpdate only checks the sticky state (and not child elements) causes anything within <Sticky /> to only re-render if the sticky state changes.

"Sub-page" `Sticky` Components

This ticket is specifically for discussion of supporting <Sticky> elements attached to in-document scrollable elements.

As an example of such a case:

<div className="scrollable"><StickyContainer><Sticky>...</Sticky></StickyContainer></div>

There are two ways to interpret the expectation in this case:

  • When <Sticky> is scrolled to the top of the scrollable element, it sticks to the top of the window.
  • When <Sticky> is scrolled to the top of the scrollable element, it sticks to the top of the element.

Let's leave the first interpretation aside for now, since it's unlikely to be a useful one. This leaves three cases for us to consider.

  1. Sticking to a scrollable element outside the StickyContainer.
    • This is most similar to the existing behavior.
  2. Sticking to a scrollable element inside the StickyContainer.
  3. Sticking to a scrollable StickyContainer.

Catch 1 (demonstrated here) – scroll events don't propagate. This implies that the only way to intercept contained scroll events is to subscribe to the scrollable element, which further implies that automagically subscribing to the correct scrollable (non-StickyContainer) element is either expensive, unreliable, or impossible.

Possible Solution 1.A – we can solve this problem by requiring the user to supply a prop identifying the scrollable element to watch, but sharp edge cases abound.

Possible Solution 1.B – we can restrict scrollable elements we'll respect to StickyContainer instances (or possibly a ScrollableStickyContainer subclass).

Catch 2position: fixed (which is used for all of our low-jank positioning) cannot be contained by scrollable elements. This would require us to implement a separate positioning computation for non-window containers.

Possible Solution 2.A – we can require the scrollable element to have position, and use a position: absolute based position calculation.

Possible Solution 2.B – we can recalculate a screen-based positioning based on the watched element when appropriate.

Catch 3StickyContainers are designed to be nested, so that more deeply nested Sticky elements will stick to one another (a la the timeline example). This is accomplished by StickyContainers subscribing to data from their ancestors about other sticky elements. StickyContainers being used within a scrollable element context MUST NOT inherit that data.

Possible Solution 3.A – we use the presence of the prop identifying the scrollable element as a sentinel for when we should avoid subscribing to ancestor data.

Possible Solution 3.B – we use a ScrollableStickyContainer subclass as the data subscription boundary.


This may not represent a complete list of the known concerns or possible solutions, but it seems like one potential solution for solving the general "sub-page" problem might look like this:

<StickyContainer>
  ...
  <Sticky key="first">
    I listen to `window`
    I stick to `window`
  </Sticky>
  ...
  <StickyContainer>
    ...
    <Sticky key="second">
      I listen to `window`
      I stick to "first"
    </Sticky>
    ...
    <ScrollableStickyContainer key="container">
      <Sticky key="inner">
        I listen to "container"
        I stick to "container"
      </Sticky>
      ...
      <StickyContainer>
        <Sticky key="fourth">
          I listen to "container"
          I stick to "inner"
        </Sticky>
      </StickyContainer>
    </ScrollableStickyContainer>
  </StickyContainer>
</StickyContainer>

To those who are interested in this feature, does this seem like an acceptable solution?

Changes to Sticky content height don't trigger `recomputeState`

When we make a component Sticky, we take it out of the flow of the document so that we can maintain its position. To prevent document reflow, we also add an appropriate amount of padding to a placeholder element, which maintains the position for everything else on the page. However, the positioned element no longer contributes height to its parent, which means that content changes inside that sticky element don't cause a height change, which means that adjustments that depend on that data aren't recomputed.

An example of this can be seen here.

  • Sticky toggling behavior functions as expected.
  • If the Sticky is activated and scrolled to the bottom of the Container, it is "pushed" by the bottom of the container, as expected.
  • If the Sticky is activated and the content changes, the bottom of the Container "pushes" against what was the bottom of the Sticky element when it was activated.

bottomOffset when Sticky element is not in viewport

I have a Sticky element that has both a top and bottom offset. When the stuck at the bottom of the container, the top of the Sticky element is not in the viewport. When scrolling up, the top of the element doesn't appear until the element is stuck at the top of the container again.

I made a jsbin to show the behaviour http://output.jsbin.com/dupagu

I've been using this component successfully so far. I tried writing a test and attempted fixing this myself but haven't spent enough time in the code base yet.

where is handleStickyStateChange in the source?

where is this prop in the source, accordingly to the doc we have this callback hook?

onStickyStateChange

Use the onStickyStateChange prop to fire a callback function when the sticky state changes:

app.jsx

<Sticky onStickyStateChange={this.handleStickyStateChange}>
  <header />
</Sticky

keep sticky thing's height in original container

Currently when the sticky thing becomes fixed the page jumps up the height of the sticky thing (and vice versa when becoming 'unfixed'). I would say this is a bug.

I am currently doing something like this:

  stickyChange(isSticky) {
    const parent = document.getElementById('way-header');
    if (isSticky) {
      const sticky = document.getElementById('sticky-nav-way');
      const clientRect = sticky.getBoundingClientRect();
      parent.setAttribute('style', 'margin-top:' + clientRect.height + 'px;');
    } else {
      parent.setAttribute('style', 'margin-top:0px;');
    }
  }

Something like this should be part of the module, I think.

Uncaught TypeError: Cannot read property 'firstChild' of undefined

react version 0.13.3

Uncaught TypeError: Cannot read property 'firstChild' of undefinedReactMount.findComponentRoot 

    @ app.js:33966ReactMount.findReactNodeByID 
    @ app.js:33912getNodeFromInstance     
    @ app.js:33401findDOMNode 
    @ app.js:40474ReactBrowserComponentMixin.getDOMNode     
    @ app.js:40412React.createClass.shouldBeSticky 
    @ app.js:24880React.createClass.handleTick       
    @ app.js:24890

Scrolling triggers render on all child components of StickyContainer

Confirmed by modifying timeline example like so:

    const Lorem = props => {
        console.log("LOREM RENDERED", props);
        return (
            <p>
                Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
                in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
            </p>
        );
    }

      let timeline = [2000, 2010].map((decade) => {
        return (
          <StickyContainer style={{zIndex: 4}}>
            <Sticky style={{zIndex: 3}}>
              <h2>{decade}s</h2>
            </Sticky>
            { _.range(0,10).map((i) => {
              return (
                <StickyContainer style={{zIndex: 2}}>
                  <Sticky>
                    <h3>{decade + i}</h3>
                  </Sticky>
                  <Lorem />
                  <Lorem />
                </StickyContainer>
              );
            })  }
          </StickyContainer>
        );
      })

This absolute wrecks performance whenever your children are at all complex.

bottomOffset not work

i set bottomOffset value, but it still scroll down to footer.

2016-05-27 18 24 06

how to solve this problem ?

Can't override onStickyStateChange handler

<Sticky onStickyStateChange={this.onStickyStateChange.bind(this)}>
This code does nothing. Helps only something like this:
Sticky.defaultProps.onStickyStateChange = this.onStickyStateChange.bind(this)
All others properties overrides.

Do not work on 4.0.1

Here are the results:

app.js:52954 Uncaught TypeError: Cannot read property 'updateOffset' of undefinedSticky._this.onScroll @ app.js:52954
bundle.js:149 failed, retry № 1 Error: Request to bg page (sync) rejected by timeout(…)

Two sticky elements inside one Container

I have something like:
<StickyContainer> <AppBar /> <Sticky> <HeaderDiv> </HeaderDiv> </Sticky> <div class="col-xs-9"> <Table /> </div> <Sticky class="col-xs-3"> <SomeContent /> </Sticky> </StickyContainer>

I really like to stick only the (to top) and (top right, but positioned right after . I have a strange behavior because of left: 0 property. If you could give me an example how I could do this trick i'll appreciate that. And thank you for your work.

Making a sticky bottom bar

Is it possible to make a sticky bottom bar using React Sticky?

It would act the same as the sticky top bar, but be triggered when the page is scrolled up from the bottom.

Thanks!
Thomas

Weird behavior when scrolling

Hard to describe so I uploaded a video. Basically when the window height is just barely tall enough to trigger the stickiness but not tall enough for it to go to its full height it will get into a loop (as long as the user continues to try to scroll).

Bug.zip

Regression introduced in v5.0.1, sticky element position not changed on horizontal scrolling

How to reproduce

  1. Go to http://rawgit.com/captivationsoftware/react-sticky/master/examples/timeline/index.html
  2. Open inspector and add min-width: 1000px to body
  3. Resize browser window to < 1000px
  4. Scroll page a lil bit down so sticky element sticks
  5. Scroll page horizontally

Expected behaviour

Sticky element moving horizontally with page, this behaviour is for v5.0.0.

Actual behaviour

Sticky elements stays in the same place. left property isn't changing.

Stop beeing sticky

Hi,
I really like the component and it helped me a lot.
But I have a question. Is it possible to define a value like bottomOffset at which the component stops being sticky and starts moving down normal again?

overflow-y: auto issue.

Hey there, I've found out that if we have an structure like this:

<body>
  <div style="overflow-y: auto; height: 100%;">
    <StickyContainer>
      <Sticky>...</Sticky>
    </StickyContainer>
  </div>
</body>

In this scenario ^. Sticky won't trigger at all, but if we remove the overflow-y or height from the container, it starts working again.

Cannot get react-sticky to work unless it is full screen

I'm trying to make react-sticky work on just a portion of the whole screen
I've recreated the timeline demo in a very stripped back fashion and made that work, but if I try to shrink it to less than full screen, the sticky behavior stops working.

I suspect it is missing CSS/HTML rather than a bug, so perhaps more of a documentation issue than code.

Stand alone demo attached. As is it shows working sticky behavior. Comment shows how to recreate the "issued.
Doesn't behave as desired on Firefox 45.0.1 or IE 11.0.9600.18205

sticky-tester-htm.txt

Version 4

Any idea on when version 4 will be in npm?

I am having problems using it straight from github:

In my packages.json file:

"react-sticky": "git://github.com/captivationsoftware/react-sticky.git",

when I do webpack build, it complains:

32% 20/53 build modulesModuleNotFoundError: Module not found: Error: Cannot resolve module 'react-sticky' in /app/reports/client/app/financials
at /app/reports/node_modules/webpack/lib/Compilation.js:229:38
at onDoneResolving (/app/reports/node_modules/webpack/lib/NormalModuleFactory.js:29:20)
at /app/reports/node_modules/webpack/lib/NormalModuleFactory.js:85:20
.
.
resolve module react-sticky in /app/reports/client/app/financials
looking for modules in /app/reports/node_modules
resolve 'file' react-sticky in /app/reports/node_modules
resolve file
/app/reports/node_modules/react-sticky is not a file
/app/reports/node_modules/react-sticky.js doesn't exist
/app/reports/node_modules/react-sticky.jsx doesn't exist
/app/reports/node_modules/react-stickyindex.js doesn't exist
/app/reports/node_modules/react-stickyindex.jsx doesn't exist
/app/reports/node_modules/react-sticky.styl doesn't exist
resolve 'file' or 'directory' /app/reports/node_modules/react-sticky
resolve file
/app/reports/node_modules/react-sticky is not a file
/app/reports/node_modules/react-sticky.js doesn't exist
/app/reports/node_modules/react-sticky.jsx doesn't exist
/app/reports/node_modules/react-stickyindex.js doesn't exist
/app/reports/node_modules/react-stickyindex.jsx doesn't exist
/app/reports/node_modules/react-sticky.styl doesn't exist
resolve directory
directory default file index
resolve file index in /app/reports/node_modules/react-sticky
/app/reports/node_modules/react-sticky/index doesn't exist
/app/reports/node_modules/react-sticky/index.js doesn't exist
/app/reports/node_modules/react-sticky/index.jsx doesn't exist
/app/reports/node_modules/react-sticky/indexindex.js doesn't exist
/app/reports/node_modules/react-sticky/indexindex.jsx doesn't exist
/app/reports/node_modules/react-sticky/index.styl doesn't exist
use lib/index.js from package.json
resolve 'file' or 'directory' lib/index.js in /app/reports/node_modules/react-sticky
resolve file
/app/reports/node_modules/react-sticky/lib/index.js doesn't exist
/app/reports/node_modules/react-sticky/lib/index.js.js doesn't exist
/app/reports/node_modules/react-sticky/lib/index.js.jsx doesn't exist
/app/reports/node_modules/react-sticky/lib/index.jsindex.js doesn't exist
/app/reports/node_modules/react-sticky/lib/index.jsindex.jsx doesn't exist
/app/reports/node_modules/react-sticky/lib/index.js.styl doesn't exist
resolve directory
/app/reports/node_modules/react-sticky/lib/index.js doesn't exist (directory default file)
/app/reports/node_modules/react-sticky/lib/index.js/package.json doesn't exist (directory description file)

Sticky should recomputeState on mount

Sometimes a sticky component comes into existence and should already be stuck. Since recomputeState isn't called until after a scroll or some other trigger, the element jumps.

This would likely be fixed by switching to requestAnimationFrame as discussed in #86

For a workaround:

  const stickImmediately = ref => ref && ref.recomputeState()

  return (
    <Sticky ref={stickImmediately}>
      <Whatever/>
    </Sticky>
  )

Trigger from bottom of element

Would it be possible to make an element sticky when the bottom of the element reaches the top of the screen? Almost like a default option for topOffset with a value of the element's height?

i get into trouble when using it.

when i scroll down over padding-bottom, than padding-bottom change to become 0, and scroll stops.

how to fix this, or my wrong config ?

hope to get your reply as soon as possible.

Multiple `Sticky` components per-`Container` are contraindicated.

In the event that two Sticky nodes are added to the same Container, both will independently stick when scrolling (as intended). However, if they share horizontal space, they will overlap one another rather than "stack".

This is not an immediate problem (and may sometimes be desirable), but likely warrants some documentation and possibly a warning.

Recalculate height of <Sticky>

If elements in <Sticky> are dynamically added/removed or if the height of elements inside are changed, the sticky's padding isn't recalculated.

Video Example:
https://youtu.be/YKk-uyKYxZA

Giving the Sticky component a ref and calling the the update() function only works if the Sticky is not active( isSticky: false)

Default style value

First, thanks for this, just an opinion here, but the default style value for sticky should not be 0 for the left position, it should be whatever the value is on the component, i have to wrap sticky into another react component to be able to accomplish that:

 componentDidMount(){
        console.log('sicky mount');
        let elm = React.findDOMNode(this.refs.elm);
        let rect = elm.getBoundingClientRect();
        var sticky = {
            position: 'fixed',
            top:0,
            left:rect.left
        };
        this.setState({sticky});
    }

and later on render

  render() {
        var sticky = this.state.sticky;
        return (
             <Sticky ref="elm" stickyStyle={sticky}>
                 <div>----- eu am a menu -----</div>
             </Sticky>
        );
    }

it works, but it renders the component twice for it to get the y position, and almost never the user will want the component to be at 0 ,0, so here is my case for making the component's left position the default.

More about header

I'm using CSS libraries and of course I have fixed header(or some of them call it sticky header/footer).
When I wrap my header component inside Sticky <header> some conflicts are starting to happen. First there are issues with z-index but that's not big of a deal. My main issue is that css transition is not happening a well as it used to, Since Sticky <header> is using fixed positioning.

I'd like to know/see more about header and if I can use it with other headers.

Thanks.

Doesn't work when parent has a transformed property

E.g. when you have a markup/CSS like this:

<div className="content">
   <Sticky>
       <ul className="content-controls"> ...</ul>
   </Sticky>
</div>

Where .content has a CSS transform property (e.g. translate), the sticky doesn't work, due to the usage of position:fixed in your script, see:
http://meyerweb.com/eric/thoughts/2011/09/12/un-fixing-fixed-elements-with-css-transforms/
and
http://stackoverflow.com/questions/15194313/webkit-css-transform3d-position-fixed-issue

Versioning

Hey guys,

First: Thank you for writing this. I'm using this in production, and it just works.

The recent change that caused for version 1.1.0 really should've caused for version 2.0.0. That is, bumping the major ( if you follow SemVer, which is kinda the standard around here :) ). Why? Because the change was not backwards compatible, since you removed the className in turn for style. I just noticed that it broke my app (because I just depended on ^1.0.4 of react-sticky).

Well, lesson learned, I now depend on strictly version 1.0.4, since I much prefer the class solution. Just wanted to let you know.

Btw.: Why not just allowing the user to do both? Or give them a callback prop onSticky so they can decide for themselves?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.