ByteSize: Creating a Condensed Header on Scroll with Flask and React
Keeping the important stuff in reach
In this edition of ByteSize we’re going to be taking a look at creating an animated condensed header using a scroll trigger. We will be using some of the basic ideas that we used in the infinite scroll component, as well as introducing a few new ones such as animated transitions.
As always we’ll be starting off with a fresh Flask + React Web App, which you can find a tutorial on how to make here.
We’ll also be using Material-UI rather extensively (including icons), so be sure to install it:
npm i @material-ui/core @material-ui/icons
If you just want the code, you can find the repo here
Getting Started
The header we’re going to be making is based off of the same one that I am integrating on Offbrand. For that we’ll need an image, the display name, username, bio, as well as the relevant social links. I am using my own Offbrand profile and placing the info in a static Data constant (in app/static/src/Data.jsx)
Now we’ll take that object and import it into a Header component file, and create the base profile header. The first step is the layout for the image, display name, username and bio (in app/static/src/Header.jsx)
Socials
Next is the social icons. We will define a special function to render our icons, including a switch function to return the proper one depending on the account. We’ll be using FontAwesome’s integration with Material-UI to retrieve the icons as well. To do that we’ll need to import another library (fg-loadcss) as well.
npm install fg-loadcss
And now for the SocialIcon component (in app/static/src/SocialIcons.jsx)
TikTok was a pain to figure out, because the icon on FontAwesome for whatever reason didnt work properly for me, so I had to improvise and find the SVG online, which I then edited and used.
Social Accordion
Now that we have our social icon function, we can import it in the Header.jsx file and use it. Since the social accounts are given as an array of objects, we can conditionally map the array (based on how many entries there are) and render the objects. I find that any more than 4 or 5 icons together can get a bit overwhelming, so I sliced the social list if it’s longer than 4 elements to put any extra into an expandable row with an accordion component. (in app/static/src/Header.jsx)
Minimalist
With our initial header finished, we’ll move on to creating the minimized variant. We can adapt the AppBar component from Material-UI (in app/static/src/Header.jsx)
A Good Listener
With both versions of our header complete, now we have to decide when we want each to be shown to the user. We’ll use a handleScroll function that toggles the small state whenever the user scrolls past the shrinkOn threshold. We’ll use useEffect to set our scroll event listener to trigger that function. Then we set the visibility of our AppBar and Container as a ternary statement based on the small state (in app/static/src/Header.jsx)
That’s Not All
But we can do more.
All that toggling on and off of our condensed header is rather abrupt. We can animate the transition to make it less jarring and appear more interactive. We can implement the Fade and Slide animations from Material-UI to easily achieve it.
The only issue you might run into is when you try to “stack” animations like the Fade and Slide together. In that case you only have to add a div between the transitions to make sure that the CSS from one doesn’t interfere with the other. For the Social Icons I also used the index value to create a progressive delay to make them enter slightly offset from one another (in app/static/src/Header.jsx)
…Side Note
One final note on performance. Using the FontAwesome icon library is great, however it’s loading time can be rather unbearable (sometimes ~9sec). There is a way to help speed up rendering to under 100ms by adding a small script to the head of your index.html file. This preloads the library with your bundle so it will be ready along with your web app, rather than waiting to start the download until later (in app/static/templates/index.html)
Finished
And with that our header component is done!
As always, thanks for reading, and be sure to check back because next time we’ll be working on adding some depth to our page with parallax animations.
You can also find more Flask + React component tutorials here:
Happy Hacking!