How to

Create interactive WebVR pages with Mozilla’s A-Frame

Design stunning 3D WebVR pages that are fully interactive with just a few HTML tags thanks to A-Frame


All the elements that make VR work are available in your mobile device, hence why Google started the cardboard project a few years ago. All a VR headset is really, is a screen and an accelerometer to know which way the screen is pointing. The problem has always been, how to make it stereoscopic and that’s where head mounts with lenses come in. What does VR mean for the web designer though?

Mozilla, the folks behind Firefox, have been working hard with Ricardo Cabello, the creator of three.js, to bring WebVR to fruition through their A-Frame library. This enables web designers to add a few simple tags to a page and it outputs a WebGL scene that can be rendered on two sides for stereoscopic display and sense the accelerometer for true WebVR. There are some interesting usability issues though. You can make the cursor display on the screen roll over content to trigger it like a click and you can also physically touch the screen, but there’s no point in rendering in stereo display with that though. Likewise if you want to make use of any HTML popups then these won’t be rendered in stereo. Take a look at for a good example of what’s possible and to inspire your own use of WebVR.


1. Get started

The library being used for this is Mozilla’s A-Frame, which can be found at It’s also already been downloaded and you can find this in the Project Files folder for this tutorial on FileSilo. Now open the Start folder in your code editor and link up the library in the head section of your document.

<script src="js/aframe.min.js"></script>

2. Create a WebVR scene

In the body section, you should now add the code to tell A-Frame to create a WebVR scene. The assets tag is used to preload assets. Here it is preloading a large equirectangular panorama image available under Creative Commons from Janne at

<img id="pano" src="assets/panorama.jpg">

3. Add the panorama

Inside the a-scene tag add the spotlight and point light as shown in the code. The spotlight is a dark grey colour while the point light is a light grey colour so as not to over saturate the scene. Then the next line adds the panorama image to the inside of a sky sphere.

<a-light type="spot" color="#333" position="-20 0 0"></a-light>
<a-light type="point" color="#AAA" position="0 5 0"></a-light>
<a-sky src="#pano"></a-sky>

4. Camera and cursor

Following the previous code add the next section, which will place a camera into the scene, with a circular cursor image attached. Save this and view your project from a web server. You can use your desktop or mobile browser to see the panorama working.

<a-camera position="0 0 0">
<a-cursor color="#fff"></a-cursor>

5. Load more images

Now move back in the a-assets tag and add two more images to load. These will be used to identify the site and give it some branding. The images can also be animated into position on the screen when the scene has loaded to give the graphics more impact on the screen.

<img id="fiji" src="assets/fiji.png">
<img id="visitor" src="assets/visitor.png">

6. Add the logo

Before the closing a-scene tag add the image that accompanies this step from FileSilo. There are several properties being added here including position and rotation. The image is scaled to 0 so that the animation tag can scale this up. The animation starts after 450 milliseconds.

<a-image id="flogo" src="#fiji" width="10" height="10" position="0 0 -35" rotation="0 3 0" scale="0 0 0">
<a-animation attribute="scale" from="0 0 0" to="0.9 0.9 0.9" begin="450" easing="ease-in-out-elastic"></a-animation>

7. Add the next image

The second image is added slightly in front of the first image and also is set to animate into the scene but a little later than the first logo. Save the page and load the page again in your mobile device. The images will appear in the display.

<a-image id="visit" src="#visitor" width="10" height="2.7" position="0 -0.1 -1" rotation="-15 8 0" scale="0 0 0">
<a-animation attribute="scale" from="0 0 0" to="0.1 0.1 0.1" begin="850" easing="ease-in-out-elastic"></a-animation>

8. Next section of images

Again these images need to be preloaded so add them into the a-assets tag. The destination’s image will be on the screen and this will be a clickable link, using the camera cursor on the screen. The resort image will then animate onto the screen.

<img id="dest" src="assets/destinations.png">
<img id="resort" src="assets/resorts.png">

9. Add the destination

The destination image needs to be added before the closing a-scene tag. This loads the right image and positions it to the left of the site image, so the user will have to turn to the left to see this in the WebVR viewport. Notice that the image has to be rotated to face the user!

<a-image id="destinations" src="#dest" width="20" height="7" position="-8 0.5 0" rotation="0 90 0" scale="0.3 0.3 0.3"></a-image>

10. Trigger the animation

In the next image there are two animations attached. The first will be triggered when the user clicks on the destination image and will bring this image onto the screen. If the user then clicks this image it will be taken off the interface.

<a-image id="resorts" src="#resort" width="20" height="7" position="-5 -1 0" rotation="0 90 0" scale="0 0 0">
<a-animation attribute="scale" begin="spiner" to="0.3 0.3 0.3" easing="ease-in-out-elastic"></a-animation>
<a-animation attribute="scale" begin="shrink" to="0 0 0" easing="ease-in-out-elastic"></a-animation>

11. Add JavaScript

Because the user needs to click a different image to trigger the animation, JavaScript needs to be added to the page before the closing body tag. This uses the emit property to trigger the name of the animation that was set up in the previous step. Take a look at this in the browser, move the cursor over the image and then simply tap the screen.

var dest = document.querySelector('#destinations');
var resort = document.querySelector('#resorts');
dest.addEventListener('click', function () {
resort.addEventListener('click', function () {

12. Preload the image

As you are probably getting the swing of this now, any assets that need to be preloaded must also be placed inside the a-assets tag. Again the next image will do the same so that it loads prior to the scene that is being displayed in the browser.

<img id="top10" src="assets/top10.png">

13. Add to the scene

The image has now been added into the WebVR scene. This time it’s placed behind the user and the image is rotated 180 degrees so that it faces the user. This image has text on it so it’s important to do this step or else it will be a struggle to read!

<a-image id="lp" src="#top10" width="5" height="5" position="0 0 3" scale="0.2 0.2 0.2" rotation="0 180 0"></a-image>

14. Detect the click

As the image is going to be a link to an external site, the following JavaScript should be added inside the script tags. Save the file and from your server, load the page into the mobile browser to see this image load the external page when clicked.

var lp = document.querySelector('#lp');
lp.addEventListener('click', function () {

15. Load a 3D model

If you look directly down there is a little ‘pinching’ of the image on the ground. That can be disguised by adding a platform that will simulate a viewing platform. You can make your own models using 3D modelling apps such as SketchUp and saving the model as a COLLADA file.

<a-asset-item id="platform" src="assets/platform.dae"></a-asset-item>

16. Place the model

After preloading the model the model will then be placed inside of the a-scene tags to add it into the scene. It’s placed directly below the camera. Save this and again load up the page in your mobile browser. If you look down with your mobile device, then you will see this 3D model in the scene.

<a-collada-model src="#platform" position="0 -0.95 0"></a-collada-model>

17. Preload the next image

The next image that is preloaded will be used to launch HTML as a popover on the screen. This won’t be in the split view because it’s HTML not WebGL, but it’s worth including so you understand how to create different types of interactions with WebVR.

<img id="attract" src="assets/attract.png">

18. Add some extra CSS

In the head section add links to the two CSS files. The first that needs to be added in is the popular Animate.CSS library and the second will be used to style the HTML overlay content that will be animated in over the top of the WebVR interface.

<link rel="stylesheet" href="css/animate.css" />
<link rel="stylesheet" href="css/style.css" />

19. HTML content

Add the HTML inside the body tag. This will then create a section of off-screen content that will be brought in when the user clicks the ‘attractions’ image that is in the VR interface. This panel can also have your own text content inside of here, so all you need to do is add it to the appropriate paragraph.

<div id="info" class="panel hidden animated">
<div class="head">
<a href="#" onclick="fade();">&#9776;</a>
<p>Text content here</p>

20. Place in the scene

The image is placed on the right of the initial image branding when the page loads. The image is rotated towards the user as with the other images by rotating it -90 degrees on the y axis. The positioning moves the image to the right of the user.

<a-image id="attractions" src="#attract" width="20" height="7" position="8 0.5 0" rotation="0 -90 0" scale="0.3 0.3 0.3"></a-image>

21. Add the functionality

Add the code that follows this step to the script tag. This will allow the content to animate into place over the WebVR scene and remove it again. Save your file and load it into your mobile web browser to test this new content sliding over the top.

var at = document.querySelector('#attractions');
var change = document.getElementById('info');
at.addEventListener('click', function () {
function fade() {


Warning: file_get_contents( failed to open stream: HTTP request failed! HTTP/1.0 500 Internal Server Error in /var/www/html/ on line 9