“This article has participated in the call for good writing activities, click to view: the back end, the big front end double track submission, 20,000 yuan prize pool waiting for you to challenge!”

preface

The reading time If the degree of Front knowledge
10min 30% React

I’ve been updating my home page recently, and I’ve just put together an article to share some thoughts. This article will talk about the implementation of each part of the site, as well as some of my thoughts and ideas about design.

If you want to write your own homepage, I hope this article can give you some inspiration.

New home page: yanhaixiang.com

Previous version

Let me show you the previous version. V1.0 was written in 2018, so old that even the local run Node-sass reported an error.

V1.0 (2018).

V2.0 (2019).

positioning

First, let’s talk about positioning, which I think is the most important part of creating a profile. I’ve seen too many people drift off course and give up, commonly known as “need ambiguity.”

For example, some people like to build everything by themselves, but they spend too much time on “building wheels”, but the website can not be built. Finally, they give up.

I used to create a personal page just to collect my Jane books and Medium articles, and write my personal profile as a page.

At that time, I was infatuated with the idea that content is king. So my idea is simple: keep it all blog posts. Never write the wheel by hand. I use whatever the wheel gives me and use the default style.

You can see that both V1.0 and V2.0 have a strong Element UI flavor, with many components remaining the same, with only minor improvements to the home page in V2.0.

Moreover, I am also a very bad thief. I prefer not to step on Markdown and editor pits, so the links to articles are in the form of external links. If I click in, I will jump to Jane book and Medium.

I don’t want to waste my time on Markdown, and I don’t want to do my own backend services and blog management.

For the new VERSION of V3.0, I no longer put various articles, because as long as you write good articles on the platform, people will naturally pay attention. On the other hand, someone might click on my page just out of curiosity.

Therefore, in order to satisfy the curiosity of your audience, I positioned it as a personal Landing Page, that is, Landing Page. Main content: highlight personal, and flashy.

style

The most important feature of landing page is big and cool, so I looked at a lot of personal home pages on the market, mainly classified into several categories: microblog category, big guy simple category and Europe and The United States huge category.

Chinese microblog category

The first type I call “Chinese microblog”, because it has a very strong microblog style. The main elements are: article body, article table of contents, article classification, tag and so on. Representative work: Ruan Yifeng’s network logs.

This kind is mainly based on the content of the article, the elements are very many and miscellaneous. There are a lot of such applications in China, which leads to serious homogeneity and makes it difficult to create new ideas. Moreover, it is very troublesome and complicated to do a good job in the style of the article, which is inconsistent with my positioning, so PASS ~

Big guy simplicity class

This is a landing page in the sense of the word, but there are so few elements that only a few lines of introduction are enough. Representative work: Yu Yu Creek’s home page.

There is not even a picture, which is the “love to see, don’t look to learn” style. But I’m not a big shot, pass

“Odd row species” class

This kind of general very show, almost not in order to see the content, but to play. Like these:

  • Read blogs in my world
  • The home page in the terminal
  • Mario home

Euramerican giant class

Foreign people prefer the style of big picture, bold lines and heavy taste and color. Dribbble and Behance have many of these designs.

The main features are: the lines are rough, the colors are bright or quietly elegant, the elements are “big”, while maintaining a simple style.

“European and American giant category” is my favorite type, jumping out of the domestic “micro-blog style” of the blog home page, and can have a beautiful design. The only difficulty was that I couldn’t design it myself, so I found a template on Dribbble and Behance and combined it with other elements as I went along.

Why not?

Then some old iron will ask:

Why don’t you go to Hexo or something and just use the free templates?

This is mainly because most of the templates are “twitter-like”, with very little dribbble design. But if you don’t have a very specific need, I suggest you stick to off-the-shelf and try not to “invent” the wheel.

That WordPress, Wix foreign site generator also has “Europe and America huge class” ah?

One reason is that the speed of access is too slow, but mainly expensive 🤣.

Technology stack

  • React
  • TypeScript
  • Sass
  • Ant Design

I’m sure many of you will feel that:

You should write your own website to attract the interviewer. Only when the interviewer asks, can you talk about how to overcome a technical point.

Here’s my idea: don’t do it. Use wheels. Don’t write by hand unless you absolutely have to!

Keep in mind whether we’re practicing or building a product. There’s nothing to say about the former, writing wheels by hand plus Posting technical articles, which is often seen on the Nuggets. For the latter, we should not focus on technology, but try to make the product perfect.

The disadvantages of building your own wheels are many:

  • Likes to invent wheels, not build them
  • They require maintenance and are no better than the wheels on the market
  • Most importantly, it’s easy to get bogged down in “how to solve the XX problem” and forget whether it’s a homepage or a wheel

Believe in another truer tenet:

If you can do it, it’s NB. If you can’t do it, it’s SB.

So, let yourself go, standing on the shoulders of giants is not sweet? Well, without further ado, let’s talk about how I did it.

Navigation bar – Nav

Classic left Logo, right List layout, there are many ways to achieve.

In the past, it was more popular to use float: left and float: right. However, this method has the disadvantage of having to clean up the float manually, and float has become a thing of the past, so pass~

Use flex space-between to finish.

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between; // Separate the left and right sides}Copy the code

Another requirement of the navigation bar is that it should be mobile, otherwise all the Nav tags are jammed together.

My implementation is to make two navigation bars and control the display of both via @media media query.

<! - level -- -- >
<ul class="horizontal">.<li class="navBtn" onclick="Open the vertical List">Vertical open button</li>
</ul>

<! Vertical -- -- -- >
<ul class="vertical">.</ul>
Copy the code
// Small screen style
@media screen and (max-width: 992px) {
  ul.horizontal { // Horizontal Nav does not come out
    li {
      display: none;

      &.navBtn {
        display: block; // The Toggle button comes out}}}ul.vertical {
    display: flex; // The vertical Nav comes out}}Copy the code

The navigation bar also has a requirement point: click on the Tab and slide to the corresponding Section. A href=”#id”> tag + div with an id embedded in it and a URL hash for navigation. The downside: The slides are too stiff, and there’s no animation.

The recommended $el.scrollintoView ({behavior: ‘smooth’}) API works fine on the PC. Disadvantages are not suitable for mobile phone, small details, can be ignored ~

const scroll = (toEl: string) = > {
  const $toEl = document.querySelector(toEl);
  if ($toEl) {
    setActiveItem(toEl);
    $toEl.scrollIntoView({ behavior: 'smooth'}); }};Copy the code

Add position: Fixed to fix the Nav component at the top of the screen for a more holistic feel.

.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 3;
  box-shadow: 0 4px 8px 0 rgba(0.0.0.0.1);
}
Copy the code

It is best to add a box-shadow effect on the outer layer to make the navigation more three-dimensional.

However, be careful not to add too obvious, it will make people feel a little intentional. The best shadow effect is not visible at first sight, but only when you look closely.

Shadows and background gradients like this are hard to pull out by hand, and are best used with GUI generators to generate CSS. Google Box-shadow Generator and tune it up!

If you say: MY GUI still can’t tune out good-looking effect how to do? The answer is: copy. They are not professional, see how professional people do, such as nuggets on the navigation bar shadow is good:

AD page – Banner

On the left, add a inside a

and you’re done. For the underlined part, you can use the pseudo-elements ::before and ::after to generate two horizontal lines, and then adjust the position: absolute to achieve the underlined effect.

.del {
  position: relative;
  &::before, &::after {
    content: ' ';
    position: absolute;
    background: #bd0000;
    width: 120%; // The width is slightly higher than that
    height: 6px;
  }
  &::before {
    left: -10%; // Handle the part that is out of width
    top: 40%;
  }
  &::after {
    left: -10%; // Handle the part that is out of width
    bottom: 30%; }}Copy the code

Typed effect can use the typed. Js library, very simple to use, this is the official small Demo:

// Can also be included with a regular script tag
import Typed from 'typed.js';

var options = {
  strings: ['<i>First</i> sentence.'.'&amp; a second sentence.'].typeSpeed: 40
};

var typed = new Typed('.element', options);
Copy the code

Typing speed, deletion speed, and DOM element retrieval logic are all reusable, so I wrapped them into a hook:

import Typed, { TypedOptions } from 'typed.js';

const useTyped = (strings: string[], extra? : TypedOptions) = > {
  const el = useRef<HTMLElement | null> (null); / / span element
  const typed = useRef<Typed | null> (null); / / Typed. Js object

  useEffect(() = > {
    const options = { // Default properties
      strings,
      typeSpeed: 100.backSpeed: 60. extra, }; typed.current =new Typed(el.current || ' ', options);

    return () = >typed.current? .destroy();/ / wipe
  }, [strings]);

  return el;
};
Copy the code

It is very convenient to use:

const Home: FC = () = > {
  const el = useTyped(strings, { loop: true });

  return (
    <span ref={el} />
  );
};
Copy the code

On the right is a Lottie animation with :: After. Let’s start with the “ripple” effect, which is actually called Pulse. The “ripple” effect is another effect, called ripple.

@keyframes pulse {
  0% {
    transform: scale(1);
    border-color: #e3342f; 100%} {transform: scale(1.2); Enlarge / /
    border-color: transparent; / / transparent}}.ball{&::before {
    content: "";
    position: absolute; // Locate to the same element
    width: 100%;
    height: 100%;
    border: 4px solid #e3342f; / / corrugated
    border-radius: 50%; / / go round
    background: transparent; // No background color
    animation: pulse 2s cubic-bezier(.57.06.27.84) infinite; / / pulse animation
    z-index: 1; // Put it on top of the original element}}Copy the code

Oh, it’s the heartbeat. No, it’s the heartbeat.

Regarding the lamb animation, it is not a Gif image, but a Lottie animation. This is Airbnb open source a set of cross-platform complete animation effect solution. In English: the advanced Gif. The animation content is driven by JSON files, which can be found free on Lottie’s website.

As for how to use it, I still encapsulated a hook:

import lottie, { AnimationConfigWithData } from 'lottie-web';

const useLottie = (path: string, extra? : AnimationConfigWithData) = > {
  const lottieRef = useRef<HTMLDivElement | null> (null); // Animation elements

  useEffect(() = > {
    if (lottieRef.current) { // Default parameters
      lottie.loadAnimation({ // Load
        container: lottieRef.current,
        path,
        renderer: 'svg'.loop: true.autoplay: true. extra, }); }} []);return lottieRef;
};
Copy the code

Pass in the JSON URL to use:

const sheepLottie = 'https://assets3.lottiefiles.com/private_files/lf30_lgesk2nm.json';

const Home: FC = () = > {
  const sheepLottieRef = useLottie(sheepLottie);

  return (
    <div ref={sheepLottieRef} />
  );
};
Copy the code

As for the arrow below, it’s a combination of Lottie + scrollIntoView({behavior: ‘smooth’}) without further elaboration.

About – the About

This part is personal introduction. Left, middle, and right are

, ,

, simple. Among them, the cube in the middle on the left is still a Lottie animation, and the “sea monster” on the right uses the HongLei font library.

In the case of strong background color, you can still use the shadow effect to highlight the three-dimensional feeling of the page, which can effectively avoid the visual “fusion” of text and background. Text-shadow is used for the text and box-shadow is used for the avatar.

The next section, the Timeline component.

Previously, WE looked at Ant Design’s Timeline component, which is implemented using positioning. I don’t like the way content divs are implemented out of the flow of the document and often collapse in height. So my Timeline component is implemented using Flex layout instead of position.

To review the Flex layout align-items property, Flex -start on top, Flex -end on bottom:

If you add flex-direction: column to the div, and the width of the left and right div is 50%, you can display the left and right div.

.timelineItem {
  width: 50%;

  &.right {
    text-align: left;
    align-self: flex-end;
  }

  &.left {
    text-align: right;
    align-self: flex-start; }}Copy the code

Then there is the implementation of the axis body, which uses ::before pseudo-element + position, but if the width is set to 1px, there will be a “mismatch” problem.

This is also easy to understand because the positioned “axis body” is protruding from the original div. You can set the left and right values to solve this problem, but 1px creates a psychological asymmetry, so I set the width to 2px and it will look fuller.

The custom node in the middle is passed a ReactChild, and the font and background are not described.

Project – personal Project

To start with how waterfall flow is implemented, you can do it in the following ways:

  • Multi-column Multi-column layout
  • The grid layout
  • Flexbox layout
  • .

Remember what we said earlier? We’re making products, not wheels, so don’t worry about how to do that and just use the existing NPM. React-navage-css is recommended. By the way, the effect of falling Water is not called “Water Fall”, but “navigation”.

const Project = () = > {
  return (
    <Masonry
      breakpointCols={{ default: 3.992: 2.786: 1 }}
      className={styles.projectList}
      columnClassName={styles.projectListColumn}
    >
      {projects.map((project) => (
        <Item {. project} key={project.logo} />
      ))}
    </Masonry>
  );
};
Copy the code
.projectList {
  display: flex;
  list-style-type: none ! important;
}

.projectListColumn {
  background-clip: padding-box;
}
Copy the code

The library has a props called breakpointCols that can display different columns at different screen widths, a very useful feature.

Color, font-size, text-shadow, etc.

Let’s talk about where the stars 1.2k ICONS came from. First of all, if you are using Travis or Coveralls, there are places where the website is automatically generated, such as clicking on the icon on Travis CI will give you the Image URL of the icon.

Don’t I have to go through the icon address on every website? And some sites may not have it. Shields. IO is a site that almost automatically generates all of the Shield ICONS we’re used to.

The only downside: clicking on the icon doesn’t take you to the site. However, you can automatically generate multiple types of ICONS, you can also set the icon style, you can also customize the Shield, what bicycle is not?

Then get these small ICONS in iconfont. Cn /, you should be familiar with them.

One last word about this animation.

Its English name is Jello, and Its Chinese name is Jelly (zhě li).

@keyframes jello {
  0% {
    transform: scale(1.1); 25%} {transform: scale(0.9.1.1); 50%} {transform: scale(1.2.0.8); 75%} {transform: scale(0.95.1.05); }}Copy the code

Contact me

Because the background of the above sections is scrolling with the page, and this page does not have too many animation effects, I set the background here as background-attachment: fixed, so that it will not appear so monotonous.

However, backgroud-attachment: Fixed cannot be used on the mobile terminal, which will become the cover style, so it should be set to the value of initial on the mobile terminal.

style={{ backgroundAttachment: isMobile ? 'initial' : 'fixed' }}
Copy the code

At the same time, I chose black and white and a single photo for the background, without too much flamboyance, also because there are too few elements in this section.

The style implementation is simple, but I won’t go into that.

animation

I’ve gone through all the sections, and this section is about animation.

The following section is highly subjective and not necessarily correct

I added a lot of entrance animations to the home page, using a library called React-Reveal. The function of this library is to display an element using an animated entrance effect when scrolling to the current element. Very practical a library. Although it is an old library, but the animation aspect is quite strong, the usage is also simple:

import Fade from 'react-reveal/Fade';

class FadeExample extends React.Component {
  render() {
    return (
      <div>
        <Fade left>
          <h1>React Reveal</h1>
        </Fade>
      </div>); }}Copy the code

More animation isn’t always better, and good design isn’t frills, it’s restraint. I’m not a designer, but I try to follow the Ant Design principles.

natural

Try not to exaggerate the animation. While React-Reveals offers a lot of fancy animation, it’s all over the place.

99% of the time, I use the fade in for the entrance, just to make the transition more natural.

efficient

For the text of the Banner page, I want to output the whole text with typed. Js:

My colleague read it and said, “Most interviewers don’t have the patience to read it”, which made me realize how inefficient it was. So I switched to showing 90% of the text directly, with only the final words printed in a loop.

Another scene is that I originally used fade in from Bottom to show each item:

There are a lot of text, pictures and ICONS in each ProjectItem, so it is difficult for people to notice the content in the first time when upward animation is used. The content can only be clearly seen after the animation is over, especially on mobile phones, which is also inefficient. Therefore, I later changed to direct fade-in to speed up the animation a little bit and also take into account the entrance animation.

Contrast & symmetry

It would be a bit repetitive if all entrances were fade in from bottom, so add contrast and symmetry to make it a little more colorful.

First of all, in the sheep Lottie animation and the downward arrow Lottie animation, the former gradually enters upward, the latter gradually enters downward, forming a contrast. Since the arrow is downward, it makes more sense to use the fade in from top.

Another place is the timeline here, the left content uses to enter the right, the right content enters the left, and also follows the logic of animation entry.

Emphasis on

The only use of exaggerated animation, is “contact me” “👍 for praise, for attention, for forwarding, one key three even!” .

Mainly because this section is really too single, add an exaggerated animation to increase a little dynamic, here used to emphasize animation should not be too much, ha ha 🤣.

color

Color respect, domestic aesthetic is given priority to with small pure and fresh generally, and as a result of took euramerican rough route, so color respect used heavy taste color, give priority to with red, yellow, orange, black.

The color values here are pretty similar. Don’t choose colors that span too much, or you’ll end up with a very fragmented page.

If you’re not too sensitive about choosing a color, Adobe’s Theme Color Recommendation has a ton of theme colors to choose from.

background

The background is really hard to choose! The difficulties are:

  • Don’t be too fancy. Otherwise it will be overwhelming, content will be the background to grab attention
  • Images should be small, many people will only open your home page once, and there will be no HTTP cache, so large backgrounds will be loaded from head to toe

Although only two points were mentioned, 90% of the pictures were not qualified: landscapes, personal photos and literary photos. However, it is often these photos that elevate the profile. What pictures are there that are small and not one-dimensional? The answer is:

In the background – repeat, repeat or background – size: cover | contain circumstances would have little change on the vision image, to meet the requirements of the above.

Here are two recommended sites that automatically generate advanced SVG backgrounds:

  • Svgwallpapers: we have 48 free WALLpapers for svGWallpapers, all of which can be customized. We pay for more than 200 wallpapers. I think 48 wallpapers is enough
  • Loading. IO, originally a website for loading animations, also makes SVG background images. There are more customized templates in it, and the free version can only generate static SVG backgrounds

To optimize the

Use React. Lazy and Suspense to subcontract React.

const Home = React.lazy(() = > import('./sections/Home'));
const About = React.lazy(() = > import('./sections/About'));
const Project = React.lazy(() = > import('./sections/Project'));
const Contact = React.lazy(() = > import('./sections/Contact'));
const Footer = React.lazy(() = > import('./sections/Footer'));

const App: FC = () = > (
  <div id="app">
    <Suspense fallback={<Loading />} ><Nav />

      <main>
        <Home />
        <About />
        <Project />
        <Contact />
      </main>

      <Footer />
    </Suspense>
  </div>
);
Copy the code

Creat-react-app-rewired and Craco didn’t work, so I’ll just manually compress it myself. There aren’t many images. The head and background images are converted to WebP format to minimize the size.

Finally, the font library optimization, it said that I used the HongLei font library, the whole library is 1.1 MB, and I used the word “sea monster”, a little unworthwhile. So, I used Fontmin to compress the font library down to 4 KB to display the font a little faster.

The last

I wrote the whole homepage in my spare time for 2 weeks. Most of my time was to try various designs, colors and backgrounds. It was quite simple in implementation. Click a Star on my Github if you like, and welcome fork and magic changes!

Github deployment and CDN acceleration are also important. Since this article is too long, I will move on to the next one.

By the way, recently opened a public account [write code sea monster], if you think I write good can also follow the fate of the attention ~