Archive

Archive for March, 2019

Extracting Text from Content Using HTML Slot, HTML Template and Shadow DOM

March 6th, 2019 No comments

Chapter names in books, quotes from a speech, keywords in an article, stats on a report — these are all types of content that could be helpful to isolate and turn into a high-level summary of what’s important.

For example, have you seen the way Business Insider provides an article’s key points before getting into the content?

That’s the sort of thing we’re going to do, but try to extract the high points directly from the article using HTML Slot, HTML Template and Shadow DOM.

These three titular specifications are typically used as part of Web Components — fully functioning custom element modules meant to be reused in webpages.

Now, what we aim to do, i.e. text extraction, doesn’t need custom elements, but it can make use of those three technologies.

There is a more rudimentary approach to do this. For example, we could extract text and show the extracted text on a page with some basic script without utilizing slot and template. So why use them if we can go with something more familiar?

The reason is that using these technologies permits us a preset markup code (also optionally, style or script) for our extracted text in HTML. We’ll see that as we proceed with this article.

Now, as a very watered-down definition of the technologies we’ll be using, I’d say:

  • A template is a set of markup that can be reused in a page.
  • A slot is a placeholder spot for a designated element from the page.
  • A shadow DOM is a DOM tree that doesn’t really exist on the page till we add it using script.

We’ll see them in a little more depth once we get into coding. For now, what we’re going to make is an article that follows with a list of key points from the text. And, you probably guessed it, those key points are extracted from the article text and compiled into the key points section.

See the Pen
Text Extraction with HTML Slot and HTML Template
by Preethi Sam (@rpsthecoder)
on CodePen.

The key points are displayed as a list with a design in between the points. So, let’s first create a template for that list and designate a place for the list to go.

<article><!-- Article content --></article>

<!-- Section where the extracted keypoints will be displayed -->
<section id='keyPointsSection'>
  <h2>Key Points:</h2>
  <ul><!-- Extracted key points will go in here --></ul>
</section>

<!-- Template for the key points list -->
<template id='keyPointsTemplate'>
  <li><slot name='keyPoints'></slot></li>
  <li style="text-align: center;">⤙&mdash;⤚</li>
</template>

What we’ve got is a semantic

with a

    where the list of key points will go. Then we have a for the list items that has two

  • elements: one with a placeholder for the key points from the article and another with a centered design.

    The layout is arbitrary. What’s important is placing a where the extracted key points will go. Whatever’s inside the will not be rendered on the page until we add it to the page using script.

    Further, the markup inside can be styled using inline styles, or CSS enclosed by :

    <template id='keyPointsTemplate'>
        <li><slot name='keyPoints'></slot></li>
        <li style="text-align: center;">⤙&mdash;⤚</li>
        <style>
            li{/* Some style */}
        </style>
    </template>

    The fun part! Let’s pick the key points from the article. Notice the value of the name attribute for the inside the (keyPoints) because we’ll need that.

    <article>
      <h1>Bears</h1>
      <p>Bears are carnivoran mammals of the family Ursidae. <span><span slot='keyPoints'>They are classified as caniforms, or doglike carnivorans</span></span>. Although only eight species of bears <!-- more content --> and partially in the Southern Hemisphere. <span><span slot='keyPoints'>Bears are found on the continents of North America, South America, Europe, and Asia</span></span>.<!-- more content --></p>
      <p>While the polar bear is mostly carnivorous, <!-- more content -->. Bears use shelters, such as caves and logs, as their dens; <span><span slot='keyPoints'>Most species occupy their dens during the winter for a long period of hibernation</span></span>, up to 100 days.</p>
      <!-- More paragraphs --> 
    </article>

    The key points are wrapped in a carrying a slot attribute value (“keyPoints“) matching the name of the placeholder inside the .

    Notice, too, that I’ve added another outer wrapping the key points.

    The reason is that slot names are usually unique and are not repeated, because one matches one element using one slot name. If there’re more than one element with the same slot name, the placeholder will be replaced by all those elements consecutively, ending in the last element being the final content at the placeholder.

    So, if we matched that one single inside the against all of the elements with the same slot attribute value (our key points) in a paragraph or the whole article, we’d end up with only the last key point present in the paragraph or the article in place of the .

    That’s not what we need. We need to show all the key points. So, we’re wrapping the key points with an outer to match each of those individual key points separately with the . This is much more obvious by looking at the script, so let’s do that.

    const keyPointsTemplate = document.querySelector('#keyPointsTemplate').content;
    const keyPointsSection = document.querySelector('#keyPointsSection > ul');
    /* Loop through elements with 'slot' attribute */
    document.querySelectorAll('[slot]').forEach((slot)=>{
      let span = slot.parentNode.cloneNode(true);
      span.attachShadow({  mode: 'closed' }).appendChild(keyPointsTemplate.cloneNode(true));
      keyPointsSection.appendChild(span);
    });

    First, we loop through every with a slot attribute and get a copy of its parent (the outer ). Note that we could also loop through the outer directly if we’d like, by giving them a common class value.

    The outer copy is then attached with a shadow tree (span.attachShadow) made up of a clone of the template’s content (keyPointsTemplate.cloneNode(true)).

    This “attachment” causes the inside the template’s list item in the shadow tree to absorb the inner carrying its matching slot name, i.e. our key point.

    The slotted key point is then added to the key points section at the end of the page (keyPointsSection.appendChild(span)).

    This happens with all the key points in the course of the loop.

    That’s really about it. We’ve snagged all of the key points in the article, made copies of them, then dropped the copies into the list template so that all of the key points are grouped together providing a nice little CliffsNotes-like summary of the article.

    Here’s that demo once again:

    See the Pen
    Text Extraction with HTML Slot and HTML Template
    by Preethi Sam (@rpsthecoder)
    on CodePen.

    What do you think of this technique? Is it something that would be useful in long-form content, like blog posts, news articles, or even Wikipedia entries? What other use cases can you think of?

    The post Extracting Text from Content Using HTML Slot, HTML Template and Shadow DOM appeared first on CSS-Tricks.

Categories: Designing, Others Tags:

The Client/Server Rendering Spectrum

March 6th, 2019 No comments

I’ve definitely been guilty of thinking about rendering on the web as a two-horse race. There is Server-Side Rendering (SSR, like this WordPress site is doing) and Client-Side Rendering (CSR, like a typical React app). Both are full of advantages and disadvantages. But, of course, the conversation is more nuanced. Just because an app is SSR doesn’t mean it doesn’t do dynamic JavaScript-powered things. And just because an app is CSR doesn’t mean it can’t leverage any SSR at all.

It’s a spectrum! Jason Miller and Addy Osmani paint that picture nicely in Rendering on the Web.

My favorite part of the article is the infographic table they post at the end of it. Unfortunately, it’s a PNG. So I took a few minutes and

-ized it, in case that’s useful to anyone.

See the Pen
The Client/Server Rendering Spectrum
by Chris Coyier (@chriscoyier)
on CodePen.

Direct Link to ArticlePermalink

The post The Client/Server Rendering Spectrum appeared first on CSS-Tricks.

Categories: Designing, Others Tags:

Refactoring Tunnels

March 6th, 2019 No comments

We’ve been writing a lot about refactoring CSS lately, from how to take a slow and methodical approach to getting some quick wins. As a result, I’ve been reading a ton about this topic and somehow stumbled upon this post by Harry Roberts about refactoring and how to mitigate the potential risks that come with it:

Refactoring can be scary. On a sufficiently large or legacy application, there can be so much fundamentally wrong with the codebase that many refactoring tasks will run very deep throughout the whole project. This puts a lot of pressure on developers, especially considering that this is their chance to “get it right this time”. This can feel debilitating: “Where do I start?” “How long is this going to take?” “How will I know if I’m doing the right thing?”

Harry then comes up with this metaphor of a refactoring tunnel where it’s really easy to find yourself stuck in the middle of a refactor and without any way out of it. He argues that we should focus on small, manageable pieces instead of trying to tackle everything at once:

Resist the temptation to refactor anything that runs right the way throughout the project. Instead, identify smaller and more manageable tasks: tasks that have a much smaller surface area, and therefore a much shorter Refactoring Tunnel.

These tasks can still aim toward a larger and more total goal but can be realised in much safer and shorter timeframes. Want to move all of your classes from BEM to BEM(IT)? Sure, but maybe just implement it on the nav first.

This way feels considerably slower, for sure, but there’s so much less risk involved.

Direct Link to ArticlePermalink

The post Refactoring Tunnels appeared first on CSS-Tricks.

Categories: Designing, Others Tags:

How To Build An Endless Runner Game In Virtual Reality (Part 1)

March 6th, 2019 No comments

How To Build An Endless Runner Game In Virtual Reality (Part 1)

How To Build An Endless Runner Game In Virtual Reality (Part 1)

Alvin Wan

2019-03-06T14:00:35+01:002019-03-06T13:18:11+00:00

Today, I’d like to invite you to build an endless runner VR game with webVR — a framework that gives a dual advantage: It can be played with or without a VR headset. I’ll explain the magic behind the gaze-based controls for our VR-headset players by removing the game control’s dependence on a keyboard.

In this tutorial, I’ll also show you how you can synchronize the game state between two devices which will move you one step closer to building a multiplayer game. I’ll specifically introduce more A-Frame VR concepts such as stylized low-poly entities, lights, and animation.

To get started, you will need the following:

  • Internet access (specifically to glitch.com);
  • A new Glitch project;
  • A virtual reality headset (optional, recommended). (I use Google Cardboard, which is offered at $15 a piece.)

Note: A demo of the final product can be viewed here.

Step 1: Setting Up A Basic Scene

In this step, we will set up the following scene for our game. It is composed of a few basic geometric shapes and includes custom lighting, which we will describe in more detail below. As you progress in the tutorial, you will add various animations and effects to transform these basic geometric entities into icebergs sitting in an ocean.


A preview of the game scene's basic geometric objects
A preview of the game scene’s basic geometric objects (Large preview)

You will start by setting up a website with a single static HTML page. This allows you to code from your desktop and automatically deploy to the web. The deployed website can then be loaded on your mobile phone and placed inside a VR headset. Alternatively, the deployed website can be loaded by a standalone VR headset.

Get started by navigating to glitch.com. Then, do the following:

  1. Click on “New Project” in the top right.
  2. Click on “hello-webpage” in the drop down.

    Glitch.com's homepage
    Glitch.com‘s homepage (Large preview)
  3. Next, click on index.html in the left sidebar. We will refer to this as your “editor”.

Glitch project index.html file
Glitch project: the index.html file (Large preview)

Start by deleting all existing code in the current index.html file. Then, type in the following for a basic webVR project, using A-Frame VR. This creates an empty scene by using A-Frame’s default lighting and camera.

<!DOCTYPE html>
<html>
  <head>
    <title>Ergo | Endless Runner Game in Virtual Reality</title>
    <script src="https://aframe.io/releases/0.7.0/aframe.min.js"></script>
  </head>
  <body>
    <a-scene>
    </a-scene>
  </body>
</html>

Note: You can learn more about A-Frame VR at aframe.io.

To start, add a fog, which will obscure objects far away for us. Modify the a-scene tag on line 8.

<a-scene fog="type: linear; color: #a3d0ed; near:5; far:20">

Moving forward, all objects in the scene will be added between the ... tags. The first item is the sky. Between your a-scene tags, add the a-sky entity.

<a-scene ...>
  <a-sky color="#a3d0ed"></a-sky>
</a-scene>

After your sky, add lighting to replace the default A-Frame lighting.

There are three types of lighting:

  • Ambient
    This is an ever-present light that appears to emanate from all objects in the scene. If you wanted a blue tint on all objects, resulting in blue-ish shadows, you would add a blue ambient light. For example, the objects in this Low Poly Island scene are all white. However, a blue ambient light results in a blue hue.
  • Directional
    This is analogous to a flashlight which, as the name suggests, points in a certain direction.
  • Point
    Again, as the name suggests, this emanates light from a point.

Just below your a-sky entity, add the following lights: one directional and one ambient. Both are light blue.

<!-- Lights -->
<a-light type="directional" castShadow="true" intensity="0.4" color="#D0EAF9;" position="5 3 1"></a-light>
<a-light intensity="0.8" type="ambient" color="#B4C5EC"></a-light>

Next, add a camera with a custom position to replace the default A-Frame camera. Just below your a-light entities, add the following:

<!-- Camera -->
<a-camera position="0 0 2.5"></a-camera>

Just below your a-camera entity, add several icebergs using low-poly cones.

<!-- Icebergs -->
<a-cone class="iceberg" segments-radial="5" segments-height="3" height="1" radius-top="0.15" radius-bottom="0.5" position="3 -0.1 -1.5"></a-cone>
<a-cone class="iceberg" segments-radial="7" segments-height="3" height="0.5" radius-top="0.25" radius-bottom="0.35" position="-3 -0.1 -0.5"></a-cone>
<a-cone class="iceberg" segments-radial="6" segments-height="2" height="0.5" radius-top="0.25" radius-bottom="0.25" position="-5 -0.2 -3.5"></a-cone>

Next, add an ocean, which we will temporarily represent with a box, among your icebergs. In your code, add the following after the cones from above.

<!-- Ocean -->
<a-box depth="50" width="50" height="1" color="#7AD2F7" position="0 -0.5 0"></a-box>

Next, add a platform for our endless runner game to take place on. We will represent this platform using the side of a large cone. After the box above, add the following:

<!-- Platform -->
<a-cone scale="2 2 2" shadow position="0 -3.5 -1.5" rotation="90 0 0" radius-top="1.9" radius-bottom="1.9" segments-radial="20" segments-height="20" height="20" emissive="#005DED" emissive-intensity="0.1">
  <a-entity id="tree-container" position="0 .5 -1.5" rotation="-90 0 0">
  </a-entity>
</a-cone>

Finally, add the player, which we will represent using a small glowing sphere, on the platform we just created. Between the tags, add the following:

<a-entity id="tree-container"...>
  <!-- Player -->
  <a-entity id="player" player>
    <a-sphere radius="0.05">
      <a-light type="point" intensity="0.35" color="#FF440C"></a-light>
    </a-sphere>
  </a-entity>
</a-entity>

Check that your code now matches the following, exactly. You can also view the full source code for step 1.

<!DOCTYPE html>
<html>
  <head>
    <title>Ergo | Endless Runner Game in Virtual Reality</title>
    <script src="https://aframe.io/releases/0.7.0/aframe.min.js"></script>
  </head>
  <body>
    <a-scene fog="type: linear; color: #a3d0ed; near:5; far:20">

      <a-sky color="#a3d0ed"></a-sky>

      <!-- Lights -->
      <a-light type="directional" castShadow="true" intensity="0.4" color="#D0EAF9;" position="5 3 1"></a-light>
      <a-light intensity="0.8" type="ambient" color="#B4C5EC"></a-light>

      <!-- Camera -->
      <a-camera position="0 0 2.5"></a-camera>

      <!-- Icebergs -->
      <a-cone class="iceberg" segments-radial="5" segments-height="3" height="1" radius-top="0.15" radius-bottom="0.5" position="3 -0.1 -1.5"></a-cone>
      <a-cone class="iceberg" segments-radial="7" segments-height="3" height="0.5" radius-top="0.25" radius-bottom="0.35" position="-3 -0.1 -0.5"></a-cone>
      <a-cone class="iceberg" segments-radial="6" segments-height="2" height="0.5" radius-top="0.25" radius-bottom="0.25" position="-5 -0.2 -3.5"></a-cone>

      <!-- Ocean -->
      <a-box depth="50" width="50" height="1" color="#7AD2F7" position="0 -0.5 0"></a-box>

      <!-- Platform -->
      <a-cone scale="2 2 2" shadow position="0 -3.5 -1.5" rotation="90 0 0" radius-top="1.9" radius-bottom="1.9" segments-radial="20" segments-height="20" height="20" emissive="#005DED" emissive-intensity="0.1">
        <a-entity id="tree-container" position="0 .5 -1.5" rotation="-90 0 0">
          <!-- Player -->
          <a-entity id="player" player>
            <a-sphere radius="0.05">
              <a-light type="point" intensity="0.35" color="#FF440C"></a-light>
            </a-sphere>
          </a-entity>
        </a-entity>
      </a-cone>
    </a-scene>
  </body>
</html>

To preview the webpage, click on “Preview” in the top left. We will refer to this as your preview. Note that any changes in your editor will be automatically reflected in this preview, barring bugs or unsupported browsers.


“Show Live” button in glitch project
“Show Live” button in glitch project (Large preview)

In your preview, you will see the following basic virtual reality scene. You can view this scene by using your favorite VR headset.

Animating Ocean and the fixed white cursor (Large preview)

This concludes the first step, setting up the game scene’s basic geometric objects. In the next step, you will add animations and use other A-Frame VR libraries for more visual effects.

Step 2: Improve Aesthetics for Virtual Reality Scene

In this step, you will add a number of aesthetic improvements to the scene:

  1. Low-poly objects
    You will substitute some of the basic geometric objects with their low-poly equivalents for more convincing, irregular geometric shapes.
  2. Animations
    You will have the player bob up and down, move the icebergs slightly, and make the ocean a moving body of water.

Your final product for this step will match the following:

Low-poly icebergs bobbing around
Low-poly icebergs bobbing around (Large preview)

To start, import A-Frame low-poly components. In ..., add the following JavaScript import:

 <script src="https://aframe.io...></script>
  <script src="https://cdn.jsdelivr.net/gh/alvinwan/aframe-low-poly@0.0.2/dist/aframe-low-poly.min.js"></script>
</head>

The A-Frame low-poly library implements a number primitives, such as lp-cone and lp-sphere, each of which is a low-poly version of an A-Frame primitive. You can learn more about A-Frame primitives over here.

Next, navigate to the section of your code. Replace all s with .

<!-- Icebergs -->
<lp-cone class="iceberg" ...></lp-cone>
<lp-cone class="iceberg" ...></lp-cone>
<lp-cone class="iceberg" ...></lp-cone>

We will now configure the low-poly primitives. All low-poly primitive supports two attributes, which control how exaggerated the low-poly stylization is:

  1. amplitude
    This is the degree of stylization. The greater this number, the more a low-poly shape can deviate from its original geometry.
  2. amplitude-variance
    This is how much stylization can vary, from vertex to vertex. The greater this number, the more variety there is in how much each vertex may deviate from its original geometry.

To get a better intuition for what these two variables mean, you can modify these two attributes in the A-Frame low-poly demo.

For the first iceberg, set amplitude-variance to 0.25. For the second iceberg, set amplitude to 0.12. For the last iceberg, set amplitude to 0.1.

<!-- Icebergs -->
<lp-cone class="iceberg" amplitude-variance="0.25" ...></lp-cone>
<lp-cone class="iceberg" amplitude="0.12" ... ></lp-cone>
<lp-cone class="iceberg" amplitude="0.1" ...></lp-cone>

To finish the icebergs, animate both position and rotation for all three icebergs. Feel free to configure these positions and rotations as desired.

The below features a sample setting:

<lp-cone class="iceberg" amplitude-variance="0.25" ...>
        <a-animation attribute="rotation" from="-5 0 0" to="5 0 0" repeat="indefinite" direction="alternate"></a-animation>
        <a-animation attribute="position" from="3 -0.2 -1.5" to="4 -0.2 -2.5" repeat="indefinite" direction="alternate" dur="12000" easing="linear"></a-animation>
      </lp-cone>
      <lp-cone class="iceberg" amplitude="0.12" ...>
        <a-animation attribute="rotation" from="0 0 -5" to="5 0 0" repeat="indefinite" direction="alternate" dur="1500"></a-animation>
        <a-animation attribute="position" from="-4 -0.2 -0.5" to="-2 -0.2 -0.5" repeat="indefinite" direction="alternate" dur="15000" easing="linear"></a-animation>
      </lp-cone>
      <lp-cone class="iceberg" amplitude="0.1" ...>
        <a-animation attribute="rotation" from="5 0 -5" to="5 0 0" repeat="indefinite" direction="alternate" dur="800"></a-animation>
        <a-animation attribute="position" from="-3 -0.2 -3.5" to="-5 -0.2 -5.5" repeat="indefinite" direction="alternate" dur="15000" easing="linear"></a-animation>
      </lp-cone>

Navigate to your preview, and you should see the low-poly icebergs bobbing around.

Bobbing player with fluctuating light
Bobbing player with fluctuating light (Large preview)

Next, update the platform and associated player. Here, upgrade the cone to a low-poly object, changing a-cone to lp-cone for . Additionally, add configurations for amplitude.

<!-- Platform -->
<lp-cone amplitude="0.05" amplitude-variance="0.05" scale="2 2 2"...>
    ...
</lp-cone>

Next, still within the platform section, navigate to the subsection of your code. Add the following animations for position, size, and intensity.

<!-- Player -->
<a-entity id="player" ...>
  <a-sphere ...>
    <a-animation repeat="indefinite" direction="alternate" attribute="position" ease="ease-in-out" from="0 0.5 0.6" to="0 0.525 0.6"></a-animation>
    <a-animation repeat="indefinite" direction="alternate" attribute="radius" from="0.05" to="0.055" dur="1500"></a-animation>
    <a-light ...>
      <a-animation repeat="indefinite" direction="alternate-reverse" attribute="intensity" ease="ease-in-out" from="0.35" to="0.5"></a-animation>
    </a-light>
  </a-sphere>
</a-entity>

Navigate to your preview, and you will see your player bobbing up and down, with a fluctuating light on a low-poly platform.

Bobbing player with fluctuating light
Bobbing player with fluctuating light (Large preview)

Next, let’s animate the ocean. Here, you can use a lightly-modified version of Don McCurdy’s ocean. The modifications allow us to configure how large and fast the ocean’s waves move.

Create a new file via the Glitch interface, by clicking on “+ New File” on the left. Name this new file assets/ocean.js. Paste the following into your new ocean.js file:

/**
 * Flat-shaded ocean primitive.
 * https://github.com/donmccurdy/aframe-extras
 *
 * Based on a Codrops tutorial:
 * http://tympanus.net/codrops/2016/04/26/the-aviator-animating-basic-3d-scene-threejs/
 */
AFRAME.registerPrimitive('a-ocean', {
  defaultComponents: {
    ocean: {},
    rotation: {x: -90, y: 0, z: 0}
  },
  mappings: {
    width: 'ocean.width',
    depth: 'ocean.depth',
    density: 'ocean.density',
    amplitude: 'ocean.amplitude',
    'amplitude-variance': 'ocean.amplitudeVariance',
    speed: 'ocean.speed',
    'speed-variance': 'ocean.speedVariance',
    color: 'ocean.color',
    opacity: 'ocean.opacity'
  }
});

AFRAME.registerComponent('ocean', {
  schema: {
    // Dimensions of the ocean area.
    width: {default: 10, min: 0},
    depth: {default: 10, min: 0},

    // Density of waves.
    density: {default: 10},

    // Wave amplitude and variance.
    amplitude: {default: 0.1},
    amplitudeVariance: {default: 0.3},

    // Wave speed and variance.
    speed: {default: 1},
    speedVariance: {default: 2},

    // Material.
    color: {default: '#7AD2F7', type: 'color'},
    opacity: {default: 0.8}
  },

  /**
   * Use play() instead of init(), because component mappings – unavailable as dependencies – are
   * not guaranteed to have parsed when this component is initialized.
   * /
  play: function () {
    const el = this.el,
        data = this.data;
    let material = el.components.material;

    const geometry = new THREE.PlaneGeometry(data.width, data.depth, data.density, data.density);
    geometry.mergeVertices();
    this.waves = [];
    for (let v, i = 0, l = geometry.vertices.length; i 

Navigate back to your index.html file. In the of your code, import the new JavaScript file:

 <script src="https://cdn.jsdelivr.net..."></script>
  <script src="./assets/ocean.js"></script>
</head>

Navigate to the section of your code. Replace the a-box to an a-ocean. Just as before, we set amplitude and amplitude-variance of our low-poly object.

<!-- Ocean -->
<a-ocean depth="50" width="50" amplitude="0" amplitude-variance="0.1" speed="1.5" speed-variance="1" opacity="1" density="50"></a-ocean>
<a-ocean depth="50" width="50" opacity="0.5" amplitude="0" amplitude-variance="0.15" speed="1.5" speed-variance="1" density="50"></a-ocean>

For your final aesthetic modification, add a white round cursor to indicate where the user is pointing. Navigate to the .

<!-- Camera -->
<a-camera ...>
  <a-entity id="cursor-mobile" cursor="fuse: true; fuseTimeout: 250"
    position="0 0 -1"
    geometry="primitive: ring; radiusInner: 0.02; radiusOuter: 0.03"
    material="color: white; shader: flat"
    scale="0.5 0.5 0.5"
    raycaster="far: 50; interval: 1000; objects: .clickable">
  <a-animation begin="fusing" easing="ease-in" attribute="scale"
    fill="backwards" from="1 1 1" to="0.2 0.2 0.2" dur="250"></a-animation>
  </a-camera>

Ensure that your index.html code matches the Step 2 source code. Navigate to your preview, and you’ll find the updated ocean along with a white circle fixed to the center of your view.

Bobbing player with fluctuating light
Bobbing player with fluctuating light (Large preview)

This concludes your aesthetic improvements to the scene. In this section, you learned how to use and configure low-poly versions of A-Frame primitives, e.g. lp-cone. In addition, you added a number of animations for different object attributes, such as position, rotation, and light intensity. In the next step, you will add the ability for the user to control the player — just by looking at different lanes.

Step 3: Add Virtual Reality Gaze Controls

Recall that our audience is a user wearing a virtual reality headset. As a result, your game cannot depend on keyboard input for controls. To make this game accessible, our VR controls will rely only on the user’s head rotation. Simply look to the right to move the player to the right, look to the center to move to the middle, and look to the left to move to the left. Our final product will look like the following.

Note: The demo GIF below was recorded on a desktop, with user drag as a substitute for head rotation.

Controlling game character with head rotation
Controlling game character with head rotation (Large preview)

Start from your index.html file. In the ... tag, import your new JavaScript file, assets/ergo.js. This new JavaScript file will contain the game’s logic.

 <script src=...></script>
  <script src="./assets/ergo.js"></script>
</head>

Then, add a new lane-controls attribute to your a-camera object:

<!-- Camera -->
<a-camera lane-controls position...>
</a-camera>

Next, create your new JavaScript file using “+ New File” to the left. Use assets/ergo.js for the filename. For the remainder of this step, you will be working in this new JavaScript file. In this new file, define a new function to setup controls, and invoke it immediately. Make sure to include the comments below, as we will refer to sections of code by those names.

/************
 * CONTROLS *
 ************/

function setupControls() {
}

/********
 * GAME *
 ********/

setupControls();

Note: The setupControls function is invoked in the global scope, because A-Frame components must be registered before the tag. I will explain what a component is below.

In your setupControls function, register a new A-Frame component. A component modifies an entity in A-Frame, allowing you to add custom animations, change how an entity initializes, or respond to user input. There are many other use cases, but you will focus on the last one: responding to user input. Specifically, you will read user rotation and move the player accordingly.

In the setupControls function, register the A-Frame component we added to the camera earlier, lane-controls. We will add an event listener for the tick event. This event triggers at every animation frame. In this event listener, hlog output at every tick.

function setupControls() {
    AFRAME.registerComponent('lane-controls', {
        tick: function(time, timeDelta) {
            console.log(time);
        }
    });
}

Navigate to your preview. Open your browser developer console by right-clicking anywhere and selecting “Inspect”. This applies to Firefox, Chrome, and Safari. Then, select “Console” from the top navigation bar. Ensure that you see timestamps flowing into the console.


Timestamps in console
Timestamps in console (Large preview)

Navigate back to your editor. Still in assets/ergo.js, replace the body of setupControls with the following. Fetch the camera rotation using this.el.object3D.rotation, and log the lane to move the player to.

function setupControls() {
  AFRAME.registerComponent('lane-controls', {
    tick: function (time, timeDelta) {
      var rotation = this.el.object3D.rotation;

      if      (rotation.y > 0.1)  console.log("left");
      else if (rotation.y 

Navigate back to your preview. Again, open your developer console. Try rotating the camera slightly, and observe console output update accordingly.

Lane log based on camera rotation
Lane log based on camera rotation (Large preview)

Before the controls section, add three constants representing the left, middle, and right lane x values.

const POSITION_X_LEFT = -0.5;
const POSITION_X_CENTER = 0;
const POSITION_X_RIGHT = 0.5;

/************
 * CONTROLS *
 ************/

...

At the start of the controls section, define a new global variable representing the player position.

/************
 * CONTROLS *
 ************/

// Position is one of 0 (left), 1 (center), or 2 (right)
var player_position_index = 1;

function setupControls() {
...

After the new global variable, define a new function that will move the player to each lane.

var player_position_index = 1;

/**
 * Move player to provided index
 * @param {int} Lane to move player to
 */
function movePlayerTo(position_index) {
}

function setupControls() {
...

Inside this new function, start by updating the global variable. Then, define a dummy position.

function movePlayerTo(position_index) {
  player_position_index = position_index;

  var position = {x: 0, y: 0, z: 0}
}

After defining the position, update it according to the function input.

function movePlayerTo(position_index) {
  ...
  if      (position_index == 0) position.x = POSITION_X_LEFT;
  else if (position_index == 1) position.x = POSITION_X_CENTER;
  else                          position.x = POSITION_X_RIGHT;
}

Finally, update the player position.

function movePlayerTo(position_index) {
    ...
document.getElementById('player').setAttribute('position', position);
}

Double-check that your function matches the following.

/**
 * Move player to provided index
 * @param {int} Lane to move player to
 */
function movePlayerTo(position_index) {
  player_position_index = position_index;
  
  var position = {x: 0, y: 0, z: 0}
  if      (position_index == 0) position.x = POSITION_X_LEFT;
  else if (position_index == 1) position.x = POSITION_X_CENTER;
  else                          position.x = POSITION_X_RIGHT;
  document.getElementById('player').setAttribute('position', position);
}

Navigate back to your preview. Open the developer console. Invoke your new movePlayerTo function from the console to ensure that it functions.

> movePlayerTo(2)  # should move to right

Navigate back to your editor. For the final step, update your setupControls to move the player depending on camera rotation. Here, we replace the console.log with movePlayerTo invocations.

function setupControls() {
  AFRAME.registerComponent('lane-controls', {
    tick: function (time, timeDelta) {
      var rotation = this.el.object3D.rotation;

      if      (rotation.y > 0.1)  movePlayerTo(0);
      else if (rotation.y 

Ensure that your assets/ergo.js matches the corresponding file in the Step 3 source code. Navigate back to your preview. Rotate the camera from side to side, and your player will now track the user’s rotation.

Controlling game character with head rotation
Controlling game character with head rotation (Large preview)

This concludes gaze controls for your virtual reality endless runner game.

In this section, we learned how to use A-Frame components and saw how to modify A-Frame entity properties. This also concludes part 1 of our endless runner game tutorial. You now have a virtual reality model equipped with aesthetic improvements like low-poly stylization and animations, in addition to a virtual-reality-headset-friendly gaze control for players to use.

Conclusion

We created a simple, interactive virtual reality model, as a start for our VR endless runner game. We covered a number of A-Frame concepts such as primitives, animations, and components — all of which are necessary for building a game on top of A-Frame VR.

Here are extra resources and next steps for working more with these technologies:

  • A-Frame VR
    Official documentation for A-Frame VR, covering the topics used above in more detail.
  • A-Frame Homepage
    Examples of A-Frame projects, exhibiting different A-Frame capabilities.
  • Low-Poly Island
    VR model using the same lighting, textures, and animations as the ones used for this endless runner game.

In the next part of this article series, I’ll show you how you can implement the game’s core logic and use more advanced A-Frame VR scene manipulations in JavaScript.

Stay tuned for next week!

Smashing Editorial(rb, ra, il)
Categories: Others Tags:

The Bottleneck of the Web

March 5th, 2019 No comments

Steve Souders, “JavaScript Dominates Browser CPU”:

Ten years ago the network was the main bottleneck. Today, the main bottleneck is JavaScript. The amount of JavaScript on pages is growing rapidly (nearly 5x in the last 7 years). In order to keep pages rendering and feeling fast, we need to focus on JavaScript CPU time to reduce blocking the browser main thread.

Alex Russell, describing a prototype of “Never-Slow Mode” in Chrome:

… blocks large scripts, sets budgets for certain resource types (script, font, css, images), turns off document.write(), clobbers sync XHR, enables client-hints pervasively, and buffers resources without Content-Length set.

Craig Hockenberry, posting an idea to the WebKit bug tracker:

Without limits, there is no incentive for a JavaScript developer to keep their codebase small and dependencies minimal. It’s easy to add another framework, and that framework adds another framework, and the next thing you know you’re loading tens of megabytes of data just to display a couple hundred kilobytes of content. …

The situation I’m envisioning is that a site can show me any advertising they want as long as they keep the overall size under a fixed amount, say one megabyte per page. If they work hard to make their site efficient, I’m happy to provide my eyeballs.

It’s easy to point a finger at frameworks and third-party scripts for large amounts of JavaScript. If you’re interested in hearing more about the size of frameworks, you might enjoy me and Dave discussing it with Jason Miller.

And speaking of third-parties, Patrick Hulce created Third Party Web: “This document is a summary of which third-party scripts are most responsible for excessive JavaScript execution on the web today.”

Sometimes name-and-shame is an effective tactic to spark change.

Addy Osmani writes about an ESLint rule that prohibits particular packages, of which you could use to prevent usage of known-to-be-huge packages. So if someone tries to load the entirety of lodash or moment.js, it can be stopped at the linting level.

Tim Kadlec ties the threads together very well in “Limiting JavaScript?” If your gut reaction on this is that JavaScript is being unfairly targeted as a villain, Tim acknowledges that:

One common worry I saw voiced was “if JavaScript, why not other resources too?”. It’s true; JavaScript does get picked on a lot though it’s not without reason. Byte for byte, JavaScript is the most significant detriment to performance on the web, so it does make sense to put some focus on reducing the amount we use.

However, the point is valid. JavaScript may be the biggest culprit more often than not, but it’s not the only one.

The post The Bottleneck of the Web appeared first on CSS-Tricks.

Categories: Designing, Others Tags:

Why I Write CSS in JavaScript

March 5th, 2019 No comments

I’m never going to tell you that writing your CSS in CSS (or some syntactic preprocessor) is a bad idea. I think you can be perfectly productive and performant without any tooling at all. But, I also think writing CSS in JavaScript is a good idea for component-based styles in codebases that build all their components with JavaScript anyway.

In this article, Max Stoiber focuses on why to write CSS in JavaScript rather than how to do it. There is one reason that resonates strongly with me, and that’s confidence. This is what styling confidence means to me.

  • Anyone on a team can work on styling a component without any fear of unintended side effects.
  • There is no pressure to come up with perfect names that will work now and forever.
  • There is no worry about the styles needing to be extremely re-usable or that they play friendly with anything else. These styles will only be used when needed and not any other time.
  • There is an obvious standard to where styles are placed in the codebase.
  • CSS in JavaScript isn’t the only answer to those things, but as Max connects to other posts on the topic, it can lead to situations where good choices happen naturally.

    There are some reasons why I don’t buy into it. Performance is one of them, like choosing CSS-in-JS is some automatic performance win. Part of the problem (and I’m guilty of doing it right here) is that CSS-in-JS is a wide scope of solutions. I’ve generally found there is no big performance wins in CSS-in-JS (more likely the opposite), but that’s irrelevant if we’re talking about something like CSS modules with the styles extracted and linked up like any other CSS.

    Direct Link to ArticlePermalink

    The post Why I Write CSS in JavaScript appeared first on CSS-Tricks.

    Categories: Designing, Others Tags:

    Building Robust Layouts With Container Units

    March 5th, 2019 No comments
    container units measure from the root of your document just like using a rem unit

    Building Robust Layouts With Container Units

    Building Robust Layouts With Container Units

    Russell Bishop

    2019-03-05T15:00:17+01:002019-03-05T14:26:14+00:00

    Container units are a specialized set of CSS variables that allow you to build grids, layouts, and components using columns and gutters. They mirror the layout functionality found in UI design software where configuring just three values provides your document with a global set of columns and gutters to measure and calculate from.

    They also provide consistent widths everywhere in your document — regardless of their nesting depth, their parent’s width, or their sibling elements. So instead of requiring a repeated set of .grid and .row parent elements, container units measure from the :root of your document — just like using a rem unit.

    (Large preview)

    What Makes Container Units Different?

    Grids from popular frameworks (such as Bootstrap or Bulma) share the same fundamental limitation: they rely on relative units such as ‘percentages’ to build columns and gutters.

    This approach ties developers to using a specific HTML structure whenever they want to use those measurements and requires parent > child nesting for widths to calculate correctly.

    Not convinced? Try for yourself:

    • Open any CSS framework’s grid demo;
    • Inspect a column and note the width;
    • Using DevTools, drag that element somewhere else in the document;
    • Note that the column’s width has changed in transit.

    Freedom Of Movement (…Not Brexit)

    Container units allow you more freedom to size elements using a set of global units. If you want to build a sidebar the width of three columns, all you need is the following:

    .sidebar {
      width: calc(3 * var(--column-unit));
      /* or columns(3) */
    }
    

    Your ...class="sidebar">... element can live anywhere inside of your document — without specific parent elements or nesting.

    Measuring three columns and using them for a sidebar.
    Measuring three columns and using them for a sidebar (Large preview)

    Sharing Tools With Designers

    Designers and developers have an excellent middle-ground that helps translate from design software to frontend templates: numbers.

    Modular scales are exceptional not just because they help designers bring harmony to their typography, but also because developers can replicate them as a simple system. The same goes for Baseline Grids: superb, self-documenting systems with tiny configuration (one root number) and massive consistency.

    Container units are set up in the same way that designers use Sketch to configure Layout Settings:


    Layout settings
    Layout settings (Large preview)

    Sketch gridlines
    Sketch gridlines (Large preview)

    Any opportunity for designers and developers to build with the same tools is a huge efficiency boost and fosters new thinking in both specialisms.

    Start Building With Container Units

    Define your grid proportions with three values:

    :root {
      --grid-width: 960;
      --grid-column-width: 60;
      --grid-columns: 12;
    }
    

    These three values define how wide a column is in proportion to your grid. In the example above, a column’s width is 60 / 960. Gutters are calculated automatically from the remaining space.

    Finally, set a width for your container:

    :root {
      --container-width: 84vw;
    }
    

    Note: --container-width should be set as an absolute unit. I recommend using viewport units or rems.

    You can update your --container-width at any breakpoint (all of your container units will update accordingly):

    @media (min-width: 800px) {
      --container-width: 90vw;
    }
        
    @media (min-width: 1200px) {
      --container-width: 85vw;
    }
        
    /* what about max-width? */
    @media (min-width: 1400px) {
      --container-width: 1200px;
    }
    
    breakpoints
    Breakpoints (Large preview)

    You’ve now unlocked two very robust units to build from:

    1. --column-unit
    2. --gutter-unit

    Column Spans: The Third And Final Weapon

    More common than building with either columns or gutters is to span across both of them:

    6 column span = 6 columns + 5 gutters
    6 column span = 6 columns + 5 gutters (Large preview)

    Column spans are easy to calculate, but not very pretty to write. For spanning across columns, I would recommend using a pre-processor:

    .panel {
      /* vanilla css */
      width: calc(6 * var(--column-and-gutter-unit) - var(--gutter-unit));
      
      /* pre-processor shortcut */
      width: column-spans(6);  
    }
    

    Of course, you can use pre-processor shortcuts for every container unit I’ve mentioned so far. Let’s put them to the test with a design example.

    Building Components With Container Units

    Let’s take a design example and break it down:


    design example
    (Large preview)

    This example uses columns, gutters and column spans. Since we’re just storing a value, container units can be used for other CSS properties, like defining a height or providing padding:

    .background-image {
      width: column-spans(9);
      padding-bottom: gutters(6);
      /* 6 gutters taller than the foreground banner */
    }
    
    .foreground-banner {
      width: column-spans(8);
      padding: gutters(2);
    }
    
    .button {
      height: gutters(3);
      padding: gutters(1);
    }
    

    Grab The Code

    :root {
      /* Grid proportions */
      --grid-width: 960;
      --grid-column-width: 60;
      --grid-columns: 12;
    
      /* Grid logic */
      --grid-gutters: calc(var(--grid-columns) - 1);
    
      /* Grid proportion logic */
      --column-proportion: calc(var(--grid-column-width) / var(--grid-width));
      --gutter-proportion: calc((1 - (var(--grid-columns) * var(--column-proportion))) / var(--grid-gutters));
    
      /* Container Units */
      --column-unit: calc(var(--column-proportion) * var(--container-width));
      --gutter-unit: calc(var(--gutter-proportion) * var(--container-width));
      --column-and-gutter-unit: calc(var(--column-unit) + var(--gutter-unit));
    
      /* Container Width */
      --container-width: 80vw;
    }
    
    @media (min-width: 1000px) {
      :root {
        --container-width: 90vw;
      }
    }
    
    @media (min-width: 1400px) {
      :root {
        --container-width: 1300px;
      }
    }
    

    Why Use CSS Variables?

    “Pre-processors have been able to do that for years with $variables — why do you need CSS variables?”

    Not… quite. Although you can use variables to run calculations, you cannot avoid compiling unnecessary code when one of the variables updates it’s value.

    Let’s take the following condensed example of a grid:

    .grid {
      $columns: 2;
      $gutter: $columns * 1rem;
      display: grid;
      grid-template-columns: repeat($columns, 1fr);
      grid-gap: $gutter;
    
      @media (min-width: $medium) {
        $columns: 3;
        grid-template-columns: repeat($columns, 1fr);
        grid-gap: $gutter;
      }
      
      @media (min-width: $large) {
        $columns: 4;
        grid-template-columns: repeat($columns, 1fr);
        grid-gap: $gutter;
      }
    }
    

    This example shows how every reference to a SASS/LESS variable has to be re-compiled if the variable changes — duplicating code over and over for each instance.

    But CSS Variables share their logic with the browser, so browsers can do the updating for you.

    .grid {
      --columns: 2;
      --gutter: calc(var(--columns) * 1rem);
      display: grid;
      grid-template-columns: repeat(var(--columns), 1fr);
      grid-gap: var(--gutter);
    
      @media (min-width: $medium) {
        --columns: 3;
      }
      
      @media (min-width: $large) {
        --columns: 4;
      }
    }
    

    This concept helps form the logic of container units; by storing logic once at the root, every element in your document watches those values as they update, and responds accordingly.

    Give it a try!

    Recommended Reading

    Smashing Editorial(dm, ra, il)
    Categories: Others Tags:

    Is Social Media Hurting Your Web Design Business?

    March 5th, 2019 No comments

    Social media is an interesting thing. As web design professionals, it can be a great opportunity to share your work and get in front of prospects who might otherwise never find you online. But for as much good as social media can do to propel your marketing efforts, it has the potential to be just as harmful to your business.

    Social Media Mistakes That Can Harm Your Web Design Business

    CareerBuilder surveyed over 1,000 people involved in the hiring process for organizations last year. What they found about the relationship between hiring and social media is quite startling.

    Even if you’re not applying to work full-time for someone else’s company, hiring managers are likely to go through a similar process when evaluating you for a freelance position. So, pay close attention to these statistics:

    • 70% of hiring organizations research candidates using social media;
    • 57% of hiring managers have chosen not to pursue a candidate because of what they found on social media;
    • 47% of organizations won’t contact a candidate if they have no online presence.

    Basically, companies are looking for a reason NOT to work with you. So, you must tread very carefully when using social media marketing.

    Here are some things to avoid:

    1. No Online Presence

    It’s funny. Use social media the wrong way, and prospective clients will rule you out as their next possible freelance designer. But don’t use social media at all, and the same can happen.

    There’s a delicate balance you must strike.

    In order to stop losing work because you don’t have an online presence, avoid the following:

    • Staying away from social media at all costs;
    • Creating profiles on social, but never posting anything;
    • Creating profiles on social, but leaving your profile incomplete, inaccurate or outdated.

    Check out Elizabeth Matthews Design’s Facebook page for an example of what to do:

    2. Too Much of an Online Presence

    Too much time spent on social media can hurt you as well — especially if you’re taking part in irrelevant conversations. If you’re pointing potential clients to your branded social media pages, then you better be engaging in conversations that fit with your niche.

    Remember: clients are looking at social media to get a sense for your professionalism and expertise. They aren’t trying to hire someone who hops in and out of social media 20 times a day. (How would you get your work done in that case?) So, keep your activity to a reasonable amount.

    Check out Veerle Pieters’ Pinterest page for an example of what to do:

    3. No Thought to Your Posts

    Social media is a free way to get in front of prospects and to learn more about what’s going on in web design! Unlike blogging and email marketing, you don’t have to be a good writer to effectively connect with others either. Just write a few words and let your images (and links) shine.

    That said, you don’t want to simply copy-and-paste the headline of an article into your social media post and call it a day. If you expect people to click on the links you’re sharing or engage with your posts, you have to say something worth listening to. If your social feed just ends up with a bunch of blog post titles and links, it’ll either look like you don’t care about sharing valuable content or you don’t understand your space very well.

    Check out Brothers Web Design Twitter page for an example of what to do:

    4. Share Bad Content

    As a general rule, you should share 20% of your own stuff on social media and 80% of stuff from other people. This way, it doesn’t seem as though you’re only there to promote your business and make more money. The reason people are willing to engage with freelancers and businesses on social media is to make a connection; not to have another sales pitch thrown in their faces.

    That said, you want to be very careful about the links, memes, and other content you share. When sharing content, it should be:

    • Published within the last week so it’s still timely and relevant;
    • Positive;
    • Valuable and not just a keyword-stuffed piece to boost SEO;
    • In line with your own web design practices;
    • Factually accurate.

    Even if you didn’t write the content, it can still reflect poorly on you for sharing something of bad quality.

    Check out Claire Brotherton’s Twitter page for an example of what to do:

    5. Discuss Sensitive Issues

    It’s easy to get wrapped up in super-charged conversations that take place on social media, especially if people are talking about matters that are close to your heart. But that’s not what future clients want to see. They want to know that you’re a professional, that you’ll come prepared to work and not bring your personal life into it. Getting involved in the wrong conversations will tell them otherwise.

    These are just some of the risky topics you’ll want to avoid:

    • Politics;
    • Drugs and alcohol;
    • Sex and relationships;
    • Violent content;
    • Anything that’s bigoted in nature.

    Check out AlchemyThree’s Instagram page for an example of what to do:

    6. Betraying Your Client’s Confidence

    This one is a huge no-no. It doesn’t matter how much of the web design community will rally behind you when a client fails to pay or you’re fed up with their endless rounds of feedback. Social media is absolutely not the place to badmouth a client — even if you don’t name them.

    The same goes for leaking any confidential or sensitive information you agreed to keep private. (Check your freelance contract. I guarantee it’s in there.) Just don’t do it.

    If you need to vent, do so with your designer pals in private. Prospective clients will see your ease with badmouthing an old or current client and take that as a sign that you’re someone not to be trusted.

    Check out Aaron Miller’s Twitter page for an example of what to do:

    Using Social Media Marketing the Right Way

    As a web designer, you have to be on social media for the purposes of marketing. Just remember that what you put out there will be judged just as harshly as the content you put on your own website. And, really, that should be a basic rule of thumb for social media:

    Never put something out there that you wouldn’t be willing to publish on your website.

    Featured image via DepositPhotos

    Add Realistic Chalk and Sketch Lettering Effects with Sketch’it – only $5!

    Source

    Categories: Designing, Others Tags:

    10 reasons why your website doesn’t get enough traffic

    March 5th, 2019 No comments
    website traffic

    Every online business you can name has one goal: increase sales and profit as much as possible. In the online environment, this all starts with a simple process: increasing traffic on your website. Look at it from this perspective, if you have an online site but you do not have enough traffic, it consumes your resources in vain.

    And yet, there are so many online sites that don’t benefit from user visits. Why? To be honest, there are quite a few reasons this could be. Below are the top 10 reasons.

    1. SEO optimization on irrelevant words

    Each niche has certain keywords that need they aim for to rank decently in Google. If you sell TVs and you rank on Google for audio systems, it doesn’t really help you. In addition, if you try to rank yourself for an extremely general keyword (like the word “TVs”) you will notice that it’s pretty much impossible to rank decently, or, at the very least, there’s an insane amount of competition.

    You have to choose something specific. Keyword research is a vital part of SEO for this very reason. Identify what users are looking for on Google and optimize those words.

    website traffic

    2. Faulty links

    Another very common cause that affects traffic is lost or defective links on the site. Have you ever gotten that infamous error 404? In this case, check where that page is on your site. You may have redirected the page, or you may have changed the URL and did not make the interconnection by 301 redirects. This can lead to the loss of links, and this will surely lead to a decrease in traffic.

    3. Penalties from Google

    Google’s penalties are quite rare, but cannot be eliminated from the equation. If you’ve tried to optimize the website, if you have multiple suspicious links to your site, if you have duplicate content, or if you do not respect Google’s rules, it will penalize you. If your website traffic has fallen sharply, or if you simply launch the site and fail to get visits, that’s probably the cause.

    website traffic

    4. Site loading speed

    Ask anyone, absolutely anyone, and they’ll tell you that slow loading screens will make them click away. People use the internet for their convenience, if you interrupt that in any way, you’ve most likely lost traffic.

    Every website should be optimized for the fastest loading speed possible. Here are a few, very quick ways to do that:

    • Use images sparingly
    • Limit the amount of GIFs and videos
    • Condense text

    Simply explained, if your website has a lot to load, it will take a while. You have to find the balance between necessary and extra content.

    5. Server issues – low-quality hosting

    And here, the problems are quite common. Visits to your site can be clearly influenced by the quality of your chosen hosting. Perhaps the site is offline fixed when a large part of your users enters it. To have quality hosting, make sure that uptime is guaranteed, as high as possible. What is the uptime of a website? You can see this here.

    6. Navigation issues

    The way users are able to navigate your site can influence traffic. If the user finds it hard to find the information they want on the site, they will definitely leave. Try to make a site as clear as possible, with an airy and clean structure. And do not forget, the content is also extremely important. It must walk the user up to the final step – the command. If he does not find interesting content on the site, the user will leave.

    The answer here, for most sites, is almost always placing the search bar in an easy to find area. Don’t hide it, make the icon small, or neglect to use one entirely. Place that search bar front and center.

    7. Unoptimized mobile site

    Over 70% of current traffic comes from mobile, and we can expect those numbers to go up increasingly in the next few years. A website that is not optimized for mobile will have clear deficiencies in attracting traffic. From the start, your website should be optimized for mobile. As more and more users are starting to use mobile devices to find what they’re looking for, your website can become obsolete really fast if it’s not mobile optimized.

    website traffic

    8. Lack of promotion

    You can’t find a website if you don’t know about its existence. It’s not enough to build a model website if it’s not promoted as it should be. Online promotion is the best way to bring traffic to a site, especially if it’s new. Closely related to SEO optimization, promotion is an unimaginable growth engine for your business.

    With that said, look for ways to advertise your website. Whether it’s organic growth, or growth created by paid ads, growth is still growth.

    9. Poor or unattractive content

    If your site does not tell a story to the visitor, they will leave and avoid ever landing on your site ever again. Poor, unskilled, and unattractive content for the user will quickly deter users from visiting your website. Try to maximize the attractiveness of content through copywriting techniques in terms of text, by combining text with pictures and techniques for creating interactive content.

    10. Incorrect indexing

    Indexing is the process by which Google sends crawlers to your site to view, categorize content, and position you on the search engine. If the indexing was done incorrectly (either because of technical difficulties or because of mistakes made by you in optimizing the site), it will not appear on Google and therefore will not have traffic. Make sure your site is properly optimized and reindeer it on Google.

    website traffic

    The conclusion

    Hopefully you don’t have any of these issues, but if you do, try to get them resolved as quickly as possible. The web holds infinite possibilities for us all, and it’s worth taking advantage of them.

    Even if you are happy with your current site traffic, try approaching a few of these issues and optimize your website as best as you can. In the end, hopefully you’ll see growth, and we all want that, don’t we?

    Read More at 10 reasons why your website doesn’t get enough traffic

    Categories: Designing, Others Tags:

    CSS Triangles, Multiple Ways

    March 5th, 2019 No comments

    I like Adam Laki’s Quick Tip: CSS Triangles because it covers that ubiquitous fact about front-end techniques: there are always many ways to do the same thing. In this case, drawing a triangle can be done:

    • with border and a collapsed element
    • with clip-path: polygon()
    • with transform: rotate() and overflow: hidden
    • with glyphs like ?

    I’d say that the way I’ve typically done triangles the most over the years is with the border trick, but I think my favorite way now is using clip-path. Code like this is fairly clear, understandable, and maintainable to me: clip-path: polygon(50% 0, 0 100%, 100% 100%); Brain: Middle top! Bottom right! Bottom left! Triangle!

    My 2nd Place method goes to an option that didn’t make Adam’s list: inline ! This kind of thing is nearly just as brain-friendly: .

    Direct Link to ArticlePermalink

    The post CSS Triangles, Multiple Ways appeared first on CSS-Tricks.

    Categories: Designing, Others Tags: