Reputation: 974
I am developing a blog and I recently added a div
element with display: flex;
to make the elements appear in the same row.
However, after making this change whenever I load the page, the elements shift a bit to the right and the font loads up a bit late. This happens only for a while, after page loads they all shift back to their expected place.
note: This doesn't show up on my localhost, but only in the production build (or when deployed)
Please check the video below to see for yourselves:
https://i.sstatic.net/z3wNe.jpg
Or if on desktop witness it yourself: https://lucid-brown-a29dc1.netlify.app/
JSX
<li>
<Link to={slug} key={slug} className="link">
<h1 className="title">
{title}
</h1>
<p className="meta">
<span>
<FaCalendar size={18} /> {prefix}
</span>
<div className="tags">
{tags && tags.map(tag =>
<Link to={`/tag/${tag.split(" ").join("-").toLowerCase()}`}>
<span key={tag}> <FaTag size={18} /> {tag} </span>
</Link>
)}
</div>
</p>
<p> {excerpt}</p>
</Link>
</li>
The corresponding css:
<style jsx>{`
:global(.link) {
width: 100%;
color: ${theme.text.color.primary};
}
li {
border: 1px solid transparent;
// border-radius: ${theme.size.radius.default};
margin: ${theme.space.l} 0 ${`calc(${theme.space.l} * 3)`};
padding: ${theme.space.inset.s};
position: relative;
transition: all ${theme.time.duration.default};
background: transparent;
&::after {
// border-top: 1px solid ${theme.line.color};
content: "";
height: 0;
position: absolute;
bottom: ${`calc(${theme.space.default} * -1.5)`};
left: 50%;
transform: translateX(-50%);
transition: all ${theme.time.duration.default};
width: 50%;
}
&:first-child {
margin-top: 10px;
}
&:last-child {
margin-bottom: 10px;
}
}
.title {
padding: ${theme.space.m} ${theme.space.s} 0;
line-height: ${theme.blog.h1.lineHeight};
font-size: ${theme.blog.h1.size};
text-remove-gap: both;
:global(.arrow) {
display: none;
position: relative;
top: 7px;
}
}
.meta {
// display: block;
font-size: 0.8em;
padding: ${theme.space.s} ${theme.space.s};
margin: ${theme.space.m} 0;
background: transparent;
.tags {
display: flex;
flex-flow: row wrap;
// flex-shrink: 0;
}
:global(svg) {
// fill: ${theme.icon.color};
fill: ${theme.text.color.primary};
opacity: 0.5;
margin: ${theme.space.inline.xs};
position: relative;
bottom: -0.4em;
}
span {
// align-items: baseline;
// display: flex;
text-transform: uppercase;
margin: ${theme.space.xs} ${theme.space.s} ${theme.space.xs} 0;
font-size: 0.8em;
}
}
p {
line-height: 1.5;
padding: 0 ${theme.space.s};
text-remove-gap: both;
}
@from-width tablet {
li {
margin: ${`calc(${theme.space.default} * 3)`} 0 ${theme.space.xl};
padding: ${theme.space.default};
&::after {
bottom: ${`calc(${theme.space.default} * -2)`};
}
&:first-child {
&::before {
top: ${`calc(${theme.space.default} * -1.75)`};
}
}
}
.title {
font-size: ${`calc(${theme.blog.h1.size} * 1.2)`};
padding: ${`calc(${theme.space.default} * 1.5) ${theme.space.default} 0`};
transition: all 0.5s;
}
.meta {
padding: ${theme.space.default} ${theme.space.default};
}
p {
padding: 0 ${theme.space.default};
}
}
@below desktop {
li {
border: 1px solid ${theme.line.color};
box-shadow: 0px 3px 2px rgba(0, 0, 0, 0.03);
margin-top: 20px;
margin-bottom: 20px;
&:first-child {
margin-top: 0;
}
&::after {
border-top: 0px;
}
}
}
@from-width desktop {
li {
margin: 0 0 0;
padding: 0 0 ${theme.space.l};
&::after {
bottom: ${`calc(${theme.space.default} * -1.5)`};
}
&:first-child {
&::before {
top: ${`calc(${theme.space.default} * -2.75)`};
}
}
}
:global(.blogItemLink:first-child) > li::before {
top: ${`calc(${theme.space.default} * -2.75)`};
}
.title {
font-size: 2.5em;
padding: ${`calc(${theme.space.default} * 1.2)`} ${theme.space.l} 0;
}
.meta {
padding: 0 ${theme.space.l} 0;
}
p {
padding: 0 ${theme.space.l} 0;
}
li {
&:hover {
border: 1px solid ${theme.line.color};
box-shadow: 0px 3px 2px rgba(0, 0, 0, 0.03);
&:after {
bottom: ${`calc(${theme.space.default} * -2.5)`};
}
:global(.gatsby-image-wrapper) {
transform: scale(1.1);
}
.title {
color: ${theme.blog.h1.hoverColor};
}
}
}
}
@media (hover: hover) {
.meta {
:global(a svg) {
transition: all 0.5s ease-in-out;
-webkit-transition: all 0.5s ease-in-out;
-moz-transition: all 0.5s ease-in-out;
}
:global(a:hover svg) {
transition: all 0.5s ease-in-out;
-webkit-transition: all 0.5s ease-in-out;
-moz-transition: all 0.5s ease-in-out;
transform: scale(1.3);
color: ${theme.color.brand.primary};
}
}
}
`}</style>
So far I have tried:
div
to span
but that aligns the tags with the prefix aboveflex
but then how else do I align items in a row?grid
should be used instead of flex
but looks like grid
is not available (need to use some css framework perhaps?)flex
at all and I am simply barking up the wrong tree?I am a css newbie so I may not be using the best practices here. Pasting the entire css here as I am not able to locate the cause of the issue. Is it because flex box is performance heavy? How can I mitigate this?
In case anyone wants to read the entire code: https://github.com/amita-shukla/blog-1/blob/master/src/components/Blog/Teaser.js
Upvotes: 3
Views: 109
Reputation: 29315
The FOUC (Flash OF Unstyled Component) comes from multiple sources. In your case, I guess that loading CSS in as JSX component <style jsx>
is blocking the rendering of the styles until they are parsed by the browser. Keep in mind that JavaScript is a render-blocking. In addition, the final behavior of your code should be tested in a gatsby build
environment.
Before the browser can render a page it has to build the DOM tree by parsing the HTML markup. During this process, whenever the parser encounters a script it has to stop and execute it before it can continue parsing the HTML.
Try adding the styles as Gatsby docs suggest:
As an initial approach, I would suggest using CSS files:
import './styles.css'
// other imports
<li>
<Link to={slug} key={slug} className="link">
<h1 className="title">
{title}
</h1>
<p className="meta">
<span>
<FaCalendar size={18} /> {prefix}
</span>
<div className="tags">
{tags && tags.map(tag =>
<Link to={`/tag/${tag.split(" ").join("-").toLowerCase()}`}>
<span key={tag}> <FaTag size={18} /> {tag} </span>
</Link>
)}
</div>
</p>
<p> {excerpt}</p>
</Link>
</li>
Assuming that styles.css is in the same folder than your React component. There, in your styles.css
:
:global(.link) {
width: 100%;
color: ${theme.text.color.primary};
}
li {
border: 1px solid transparent;
// border-radius: ${theme.size.radius.default};
margin: ${theme.space.l} 0 ${`calc(${theme.space.l} * 3)`};
padding: ${theme.space.inset.s};
position: relative;
transition: all ${theme.time.duration.default};
background: transparent;
&::after {
// border-top: 1px solid ${theme.line.color};
content: "";
height: 0;
position: absolute;
bottom: ${`calc(${theme.space.default} * -1.5)`};
left: 50%;
transform: translateX(-50%);
transition: all ${theme.time.duration.default};
width: 50%;
}
&:first-child {
margin-top: 10px;
}
&:last-child {
margin-bottom: 10px;
}
}
.title {
padding: ${theme.space.m} ${theme.space.s} 0;
line-height: ${theme.blog.h1.lineHeight};
font-size: ${theme.blog.h1.size};
text-remove-gap: both;
:global(.arrow) {
display: none;
position: relative;
top: 7px;
}
}
.meta {
// display: block;
font-size: 0.8em;
padding: ${theme.space.s} ${theme.space.s};
margin: ${theme.space.m} 0;
background: transparent;
.tags {
display: flex;
flex-flow: row wrap;
// flex-shrink: 0;
}
:global(svg) {
// fill: ${theme.icon.color};
fill: ${theme.text.color.primary};
opacity: 0.5;
margin: ${theme.space.inline.xs};
position: relative;
bottom: -0.4em;
}
span {
// align-items: baseline;
// display: flex;
text-transform: uppercase;
margin: ${theme.space.xs} ${theme.space.s} ${theme.space.xs} 0;
font-size: 0.8em;
}
}
p {
line-height: 1.5;
padding: 0 ${theme.space.s};
text-remove-gap: both;
}
@from-width tablet {
li {
margin: ${`calc(${theme.space.default} * 3)`} 0 ${theme.space.xl};
padding: ${theme.space.default};
&::after {
bottom: ${`calc(${theme.space.default} * -2)`};
}
&:first-child {
&::before {
top: ${`calc(${theme.space.default} * -1.75)`};
}
}
}
.title {
font-size: ${`calc(${theme.blog.h1.size} * 1.2)`};
padding: ${`calc(${theme.space.default} * 1.5) ${theme.space.default} 0`};
transition: all 0.5s;
}
.meta {
padding: ${theme.space.default} ${theme.space.default};
}
p {
padding: 0 ${theme.space.default};
}
}
@below desktop {
li {
border: 1px solid ${theme.line.color};
box-shadow: 0px 3px 2px rgba(0, 0, 0, 0.03);
margin-top: 20px;
margin-bottom: 20px;
&:first-child {
margin-top: 0;
}
&::after {
border-top: 0px;
}
}
}
@from-width desktop {
li {
margin: 0 0 0;
padding: 0 0 ${theme.space.l};
&::after {
bottom: ${`calc(${theme.space.default} * -1.5)`};
}
&:first-child {
&::before {
top: ${`calc(${theme.space.default} * -2.75)`};
}
}
}
:global(.blogItemLink:first-child) > li::before {
top: ${`calc(${theme.space.default} * -2.75)`};
}
.title {
font-size: 2.5em;
padding: ${`calc(${theme.space.default} * 1.2)`} ${theme.space.l} 0;
}
.meta {
padding: 0 ${theme.space.l} 0;
}
p {
padding: 0 ${theme.space.l} 0;
}
li {
&:hover {
border: 1px solid ${theme.line.color};
box-shadow: 0px 3px 2px rgba(0, 0, 0, 0.03);
&:after {
bottom: ${`calc(${theme.space.default} * -2.5)`};
}
:global(.gatsby-image-wrapper) {
transform: scale(1.1);
}
.title {
color: ${theme.blog.h1.hoverColor};
}
}
}
}
@media (hover: hover) {
.meta {
:global(a svg) {
transition: all 0.5s ease-in-out;
-webkit-transition: all 0.5s ease-in-out;
-moz-transition: all 0.5s ease-in-out;
}
:global(a:hover svg) {
transition: all 0.5s ease-in-out;
-webkit-transition: all 0.5s ease-in-out;
-moz-transition: all 0.5s ease-in-out;
transform: scale(1.3);
color: ${theme.color.brand.primary};
}
}
}
Note: of course changing the variables for CSS-based ones. Alternatively, use styled-components.
Keep also in mind that if you want to add global styles, the easiest and native approach is using the gatsby-browser.js
file:
import "./src/styles/global.css"
// or:
// require('./src/styles/global.css')
Upvotes: 2