Design+Code logo

Quick links

Suggested search

Export in React Site image 1

React export

On the top bar of Spline, click Export, select Code, then select React from the dropdown menu. In other words, Spline and React are completely compatible. It includes the URL to the scene but also, a code snippets.

Export in React Site image 2

Figma link

To follow this part of the tutorial, you also need the Figma design file. We will recreate this design from Figma in React. I will leave the link to the Figma design in the description below. The Design system includes fonts, colors, components, and styles. There is also a static web design and a mobile design below that.

Demo

Here's a demo of what we're going to build. This website is fully interactive, including buttons and the scene. Our goal will be to learn how to make the Spline scene fullscreen and how to return it to its original size. Additionally, we will discuss responsiveness.

Template

In order to follow along with me, I highly recommend downloading or duplicating the CodeSandBox template in the description below. I will also include a link to the final template.

Starting template

The starting template has a few components such as the CloseButton, CourseButton, DownloadButton, Header, Logo, PlayButton and SplineScene. The Spline scene file is the same code as the export React in Spline. Then, we have some custom fonts, images and the TextStyles. The TextStyles is similar to the Design system in Figma converted in code.

Logo

Let’s start simple with the logo. At the top left, we have a Logo component, so let’s import it and use in HTML. Then, to position it, declare a new variable called LogoContainer which is a div.

import Logo from "./components/Logo";

<LogoContainer>
	<Logo />
</LogoContainer>

const LogoContainer = styled.div`
  position: absolute;
  top: 44px;
  left: 0px;
`;

Text Container

Then, we have a bunch of texts. Declare a TextContainer, a Title and a Description. Don’t forget to import the TextStyles.

<TextContainer>
	<Title>3D Room with Game Controls</Title>
	<Description>
		Learn how to create a 3D scene in Spline with game interactions
		like moving, jumping, mouse events and dark mode state.
	</Description>
</TextContainer>

const TextContainer = styled.div`
  display: grid;
  gap: 24px;
  max-width: 460px;
  padding: 225px 0px 0px 56px;
`;

const Title = styled(TextStyles.H1)``;

const Description = styled.p`
  max-width: 360px;
  text-align: left;
  font-family: "Inter", BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu,
    Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
  font-style: normal;
  font-weight: 500;
  font-size: 17px;
  line-height: 21px;
  color: rgba(0, 0, 0, 0.6);
  margin: 0;
`;

Button Container

Then, we have the download and play button. Declare a ButtonContainer with a grid so we can position them side by side. For the download button, we can add the a tag to download the file. Make sure to import the download, play button and the download file.

import DownloadButton from "./components/DownloadButton";
import PlayButton from "./components/PlayButton";
import DownloadFile from "./smart_home_final.spline.zip";

<ButtonContainer>
	<a href={DownloadFile} target="_blank" rel="noreferrer">
		<DownloadButton />
	</a>
	<PlayButton />
</ButtonContainer>

const ButtonContainer = styled.div`
  display: grid;
  grid-template-columns: auto auto;
  justify-content: start;
  gap: 20px;
  background: linear-gradient(
    270deg,
    #f1f1f1 12.86%,
    rgba(255, 255, 255, 0) 83.72%
  );
  mix-blend-mode: normal;
  padding: 40px 0px 40px 56px;
  margin-top: 53px;

  a {
    text-decoration: none;
  }
`;

Shadow

Right below the buttons, we have a shadow and the best way to replicate this UI is by using a gradient.

<GradientLine />

const GradientLine = styled.div`
  width: 100%;
  height: 48px;
  background: linear-gradient(
    185deg,
    rgba(0, 0, 0, 0.2) 0%,
    rgba(255, 255, 255, 0) 50%
  );
`;

Controls

Next, we have the controls. So, let’s declare the container, a Subtitle and the ControlImage. Don’t forget to import the image.

import ImageControl from "./images/controls.png";

<ControlContainer1>
	<Subtitle>Keyboard key</Subtitle>
	<ControlImage src={ImageControl} alt="controls image" />
</ControlContainer1>

const ControlContainer1 = styled.div`
  display: block;
`;

const Subtitle = styled(TextStyles.BodyMain)`
  color: rgba(0, 0, 0, 0.6);
  margin-top: 14px;
  padding-left: 56px;
`;

const ControlImage = styled.img`
  max-width: 326px;
  padding: 14px 0px 0px 56px;
`;

Container

Based on the design, you can see that we have a left side which contains the texts, buttons and controls, and the right layout which has the Spline scene. Let’s insert a container to keep all these elements together.

<ContentWrapper>
	<Container>

	</Container>
</ContentWrapper>

const ContentWrapper = styled.div`
  display: grid;
  grid-template-columns: auto 855px;
  max-width: 1440px;
  width: 100%;
  margin: 0 auto;
`;

const Container = styled.div`
  position: relative;
`;

Spline Container

On the other side, declare a Spline Container which will contain the Header, CloseButton and the Spline scene.

import Header from "./components/Header";
import SplineScene from "./components/SplineScene";
import CloseButton from "./components/CloseButton";

<SplineContainer>
	<Header />
	<CloseButton/>
	<SplineScene/>
</SplineContainer>

const SplineContainer = styled.div`
  position: relative;
  padding: 24px 20px 24px 0px;

  .closeButton {
    top: 54%;
    left: -32px;
  }
`;

useState

Similar to Spline, React has a state system called useState. The goal is to pass from window size to fullscreen and vice versa. First, import useState from react and then, set the state. The initial value is false. The PlayButton is the trigger so we will set the onClick event on it and set the state to true.

const [isOpen, setIsOpen] = useState(false);

<PlayButton onClick={() => setIsOpen(true)} />

Props

When you click on the PlayButton, nothing really happens, the event is there and the state is changing but we aren’t changing the CSS appropriately. In SplineContainer, we will use the state to switch between 2 different styles.

<SplineContainer isOpen={isOpen}>
	<Header />
	<CloseButton isOpen={isOpen} onClick={() => setIsOpen(false)} />
	<SplineScene />
</SplineContainer> 

const SplineContainer = styled.div`
  position: ${(props) => (props.isOpen ? "fixed" : "relative")};
  padding: ${(props) => (props.isOpen ? "0px" : "24px 20px 24px 0px")};

  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  overflow: auto;

  .spline {
    border-radius: ${(props) => (props.isOpen ? "0px" : "20px")};
  }
`;

Responsiveness

It is really important to think about how your website will look like on a smaller screen. If it is not adaptive, your website will break at a certain screen size. To fix this issue, we will use media queries. There’s 3 screen sizes that we have to take into consideration: over 1400px, below 1400px and below 560px. At 1400px, the layout changes from left and right side to a single column. When this happens, we need to change the position of the close button. The text container will have less paddings. We will remove the gradient. We will also remove the controls.

const ContentWrapper = styled.div`
  @media (max-width: 1400px) {
    grid-template-columns: 1fr;
    align-content: center;
    padding-bottom: 40px;
  }
`;

const SplineContainer = styled.div`
  @media (max-width: 1400px) {
    padding: ${(props) => (props.isOpen ? "0px" : "0px 20px 10px")};

    .closeButton {
      top: -44px;
      left: 50%;
      margin-left: -50px;
      transform: rotate(90deg);
    }
  }
`;

const GradientLine = styled.div`
  @media (max-width: 1400px) {
    display: none;
  }
`;

const ControlContainer1 = styled.div`
  @media (max-width: 1400px) {
    display: none;
  }
`;

Second controls

In the design, we can see that the controls are below the scene, there’s multiple ways to go about this but I think the most understandable one is to add a second controls. Set the display to none and only show when we hide the first one.

<ControlContainer2>
	<Subtitle>Keyboard key</Subtitle>
	<ControlImage src={ImageControl} alt="controls image" />
</ControlContainer2>

const ControlContainer2 = styled.div`
  display: none;

  @media (max-width: 1400px) {
    display: block;
  }
`;

Mobile responsiveness

At the smaller screen size, the text container will have less paddings. On the button container, we will change the layout to be a single column. Reduce the paddings on the subtitle and the image.

const TextContainer = styled.div`
  @media (max-width: 560px) {
    padding: 145px 20px 0px;
  }
`;

const ButtonContainer = styled.div`
  @media (max-width: 560px) {
    grid-template-columns: auto;
    justify-content: center;
    justify-items: center;
    align-content: center;
    padding: 32px 20px;
    margin-top: 40px;
  }
`;

const Subtitle = styled(TextStyles.BodyMain)`
  @media (max-width: 560px) {
    padding: 8px 20px;
  }
`;

const ControlImage = styled.img`
  @media (max-width: 560px) {
    padding: 8px 20px;
  }
`;

BACK TO

URL & Embed

READ NEXT

Performance & 3D Vitals

Templates and source code

Download source files

Download the videos and assets to refer and learn offline without interuption.

check

Design template

check

Source code for all sections

check

Video files, ePub and subtitles

Subtitles

Videos

Assets

Meet the instructor

We all try to be consistent with our way of teaching step-by-step, providing source files and prioritizing design in our courses.

Willie Yam

Front-end/UI developer at Design+Code

I do UI coding. HTML/CSS/JS/SWIFTUI dev.

icon

10 courses - 37 hours

course logo

Design and Prototype an App with Play

Build a completely functional prototype without writing a single line of code from your phone

3 hrs

course logo

Create a 3D site with game controls in Spline

Build an interactive 3D scene implemented on a ReactJS site using Figma and Spline

2 hrs

course logo

Build a Movie Booking App in SwiftUI

Learn how to create an iOS app based on a beautiful UI design from Figma with interesting animations and interactions, create a custom tab bar and use navigation views to build a whole flow

1 hrs

course logo

Build Quick Apps with SwiftUI

Apply your Swift and SwiftUI knowledge by building real, quick and various applications from scratch

11 hrs

course logo

CSS Handbook

A comprehensive series of tutorials that encompass styled-components, CSS, and all layout and UI developments

1 hrs

course logo

Advanced React Hooks

Learn how to build a website with Typescript, Hooks, Contentful and Gatsby Cloud

5 hrs

course logo

Unity for Designers

If you want to make a game and don't know where to start, you are in the right place. I will teach you how to use Unity, code in C# and share essential tips and tricks to make your first game.

5 hrs

course logo

Create a Javascript Game

Learn how to create a web game using Phaser 3, a popular javascript game engine. Draw a map using an editor, implement the player, make the player move, apply physics, collisions, and implement the enemies.

2 hrs

course logo

Build an ARKit 2 App

Introduction to ARKit and learn how to make your own playground. You will be able to add models or even your own designs into the app and play with them

4 hrs

course logo

Create a SpriteKit Game

Overview of SpriteKit a powerful 2D sprite-based framework for games development from Apple and learn how to create your very own platform

3 hrs