Innovation Can’t Keep the Web Fast

Every so often, the fruits of innovation bear fruit in the form of improvements to the foundational layers of the web. In 2015, HTTP/2 became a published standard in an effort to update an aging protocol. This was was both necessary and overdue, as HTTP/1 rendered web performance as an arcane sort of discipline in the form of strange workarounds of its limitations. Though HTTP/2 proliferation isn’t absolute — and there are kinks yet to be worked out — I don’t think it’s a stretch to say the web is better off because of it.

Unfortunately, the rollout of HTTP/2 has presided over a 102% median increase of bytes transferred over mobile the last four years. If we look at the 90th percentile of that same dataset — because it’s really the long tail of performance we need to optimize for — we see an increase of 239%. From 2016 (PDF warning) to 2019, the average mobile download speed in the U.S. has increased by 73%. In Brazil and India, average mobile download speeds increased by 75% and 28%, respectively, in that same period of time.

While page weight alone doesn’t necessarily tell the whole story of the user experience, it is, at the very least, a loosely related phenomenon which threatens the collective user experience. The story that HTTPArchive tells through data acquired from the Chrome User Experience Export (CrUX) can be interpreted a number of different ways, but this one fact is steadfast and unrelenting: most metrics gleaned from CrUX over the last couple of years show little, if any improvement despite various improvements in browsers, the HTTP protocol, and the network itself.

Given these trends, all that can be said of the impact of these improvements at this point is that it has helped to stem the tide of our excesses, but precious little to reduce them. Despite every significant improvement to the underpinnings of the web and the networks we access it through, we continue to build for it in ways that suggest we’re content with the never-ending Jevons paradox in which we toil.

If we’re to make progress in making a faster web for everyone, we must recognize some of the impediments to that goal:

  1. The relentless desire to monetize every square inch of the web, as well as the army of third party vendors which fuel the research mandated by such fevered efforts.
  2. Workplace cultures that favor unrestrained feature-driven development. This practice adds to — but rarely takes away from — what we cram down the wire to users.
  3. Developer conveniences that make the job of the developer easier, but can place an increasing cost on the client.

Counter-intuitively, owners of mature codebases which embody some or all of these traits continue to take the same unsustainable path to profitability they always have. They do this at their own peril, rather than acknowledge the repeatedly established fact that performance-first development practices will do as much — or more — for their bottom line and the user experience.

It’s with this understanding that I’ve come to accept that our current approach to remedy poor performance largely consists of engineering techniques that stem from the ill effects of our business, product management, and engineering practices. We’re good at applying tourniquets, but not so good at sewing up deep wounds.

It’s becoming increasingly clear that web performance isn’t solely an engineering problem, but a problem of people. This is an unappealing assessment in part because technical solutions are comparably inarguable. Content compression works. Minification works. Tree shaking works. Code splitting works. They’re undeniably effective solutions to what may seem like entirely technical problems.

The intersection of web performance and people, on the other hand, is messy and inconvenient. Unlike a technical solution as clearly beneficial as HTTP/2, how do we qualify what successful performance cultures look like? How do we qualify successful approaches to get there? I don’t know exactly what that looks like, but I believe a good template is the following marriage of cultural and engineering tenets:

  1. An organization can’t be successful in prioritizing performance if it can’t secure the support of its leaders. Without that crucial element, it becomes extremely difficult for organizations to create a culture in which performance is the primary feature of their product.
  2. Even with leadership support, performance can’t be effectively prioritized if the telemetry isn’t in place to measure it. Without measurement, it becomes impossible to explain how product development affects performance. If you don’t have the numbers, no one will care about performance until it becomes an apparent crisis.
  3. When you have the support of leadership to make performance a priority and the telemetry in place to measure it, you still can’t get there unless your entire organization understands web performance. This is the time at which you develop and roll out training, documentation, best practices, and standards the organization can embrace. In some ways, this is the space which organizations have already spent a lot of time in, but the challenging work is in establishing feedback loops to assess how well they understand and have applied that knowledge.
  4. When all of the other pieces are finally in place, you can start to create accountability in the organization around performance. Accountability doesn’t come in the form of reprisals when your telemetry tells you performance has suffered over time, but rather in the form of guard rails put in place in the deployment process to alert you when thresholds have been crossed.

Now comes the kicker: even if all of these things come together in your workplace, good outcomes aren’t guaranteed. Barring some regulation that forces us to address the poorly performing websites in our charge — akin to how the ADA keeps us on our toes with regard to accessibility — it’s going to take continuing evangelism and pressure to ensure performance remains a priority. Like so much of the work we do on the web, the work of maintaining a good user experience in evolving codebases is never done. I hope 2020 is the year that we meaningfully recognize that performance is about people, and adapt accordingly.

As technological innovations such as HTTP/3 and 5G emerge, we must take care not to rest on our laurels and simply assume they will heal our ills once and for all. If we do, we’ll certainly be having this discussion again when the successors to those technologies loom. Innovation alone can’t keep the web fast because making the web fast — and keeping it that way — is the hard work we can only accomplish by working together.

The post Innovation Can’t Keep the Web Fast appeared first on CSS-Tricks.

Smaller HTML Payloads with Service Workers

Short story: Philip Walton has a clever idea for using service workers to cache the top and bottom of HTML files, reducing a lot of network weight.

Longer thoughts: When you’re building a really simple website, you can get away with literally writing raw HTML. It doesn’t take long to need a bit more abstraction than that. Even if you’re building a three-page site, that’s three HTML files, and your programmer’s mind will be looking for ways to not repeat yourself. You’ll probably find a way to “include” all the stuff at the top and bottom of the HTML, and just change the content in the middle.

I have tended to reach for PHP for that sort of thing in the past (<?php include('header.php); ?>), although these days I’m feeling much more Jamstack-y and I’d probably do it with Eleventy and Nunjucks.

Or, you could go down the SPA (Single Page App) route just for this basic abstraction if you want. Next and Nuxt are perhaps a little heavy-handed for a few includes, but hey, at least they are easy to work with and the result is a nice static site. The thing about these JavaScript-powered SPA frameworks (Gatsby is in here, too), is that they “hydrate” from static sites into SPAs as the JavaScript loads. Part of the reason for that is speed. No longer does the browser need to reload and request a whole big HTML page again to render; it just asks for whatever smaller amount of data it needs and replaces it on the fly.

So in a sense, you might build a SPA because you have a common header and footer and just want to replace the guts, for efficiencies sake.

Here’s Phil:

In a traditional client-server setup, the server always needs to send a full HTML page to the client for every request (otherwise the response would be invalid). But when you think about it, that’s pretty wasteful. Most sites on the internet have a lot of repetition in their HTML payloads because their pages share a lot of common elements (e.g. the <head>, navigation bars, banners, sidebars, footers etc.). But in an ideal world, you wouldn’t have to send so much of the same HTML, over and over again, with every single page request.

With service workers, there’s a solution to this problem. A service worker can request just the bare minimum of data it needs from the server (e.g. an HTML content partial, a Markdown file, JSON data, etc.), and then it can programmatically transform that data into a full HTML document.

So rather than PHP, Eleventy, a JavaScript framework, or any other solution, Phil’s idea is that a service worker (a native browser technology) can save a cache of a site’s header and footer. Then server requests only need to be made for the “guts” while the full HTML document can be created on the fly.

It’s a super fancy idea, and no joke to implement, but the fact that it could be done with less tooling might be appealing to some. On Phil’s site:

 on this site over the past 30 days, page loads from a service worker had a 47.6% smaller network payloads, and a median First Contentful Paint (FCP) that was 52.3% faster than page loads without a service worker (416ms vs. 851ms).

Aside from configuring a service worker, I’d think the most finicky part is having to configure your server/API to deliver a content-only version of your stuff or build two flat file versions of everything.

Direct Link to ArticlePermalink

The post Smaller HTML Payloads with Service Workers appeared first on CSS-Tricks.

29 Days Of February (2020 Wallpapers Edition)

29 Days Of February (2020 Wallpapers Edition)

29 Days Of February (2020 Wallpapers Edition)

Cosima Mielke

2020-01-31T11:00:00+00:00 2020-02-01T00:08:37+00:00

What will you make of the extra day that February has in store for us this year? Visit an old friend, explore a new place, or use it to get stuff done you have put off for so long? Whatever you might have planned this month, our new collection of wallpapers is bound to cater for a little inspiration spark along the way.

Created by artists and designers from all across the globe, the wallpapers come in versions with and without a calendar for February 2020 and can be downloaded for free — a Smashing tradition that has been going on for more than nine years already. A big thank-you to everyone who challenged their creative skills and shared their artworks with us this time around!

As a little bonus goodie, we also added some February favorites from our archives to the end of this post. Because, well, some things are just too good to be forgotten, right? Enjoy!

Please note that:

  • All images can be clicked on and lead to the preview of the wallpaper,
  • We respect and carefully consider the ideas and motivation behind each and every artist’s work. This is why we give all artists the full freedom to explore their creativity and express emotions and experience through their works. This is also why the themes of the wallpapers weren’t anyhow influenced by us but rather designed from scratch by the artists themselves.

Submit your wallpaper

Do you have an idea for a March wallpaper design? We are always looking for creative talent to be featured in our wallpapers posts. Don’t be shy, join in! →

It’s A Cupcake Kind Of Day!

“Sprinkles are fun, festive and filled with love… especially when topped on a cupcake! Everyone is creative in their own unique way, so why not try baking some cupcakes and decorating them for your sweetie this month? Something homemade, like a cupcake or DIY craft is always a sweet gesture.” — Designed by Artsy Cupcake from the United States.

It’s A Cupcake Kind Of Day!

Well It’s Groundhog Day… Again!

“‘It’s always Groundhog Day and there’s nothing I can do about it.’ as the inimitable Bill Murray said in the timeless Groundhog Day movie. We used a photo manipulation technique to come up with this sense of being caught in a time loop. When the Groundhog emerges from his den on this Groundhog day, will it forecast an early Spring or six more weeks of winter? Find out on February 2nd!” — Designed by Alistair Dodds from the United Kingdom.

Well It’s Groundhog Day… Again!

Love Is in the Air

— Designed by MasterBundles from the United States.

Love Is in the Air

National Don’t Cry Over Spilled Milk Day

“If ‘don’t cry over spilled milk’ hasn’t yet been your mantra, it should definitely become now. The English proverb, whose national day is celebrated on February 11th, stands as a reminder not to worry over things of the past that cannot be undone, but to think positive, and keep our spirits high. Life is too short to let the trifling issues bother us.” — Designed by Pop Art Studio from Serbia.

National Don’t Cry Over Spilled Milk Day

The Rainbow Is Here!

“In February the weather is crazy. One day it is sunny and the next it is snowing. And that is its charm…” — Designed by Veronica Valenzuela from Spain.

The Rainbow Is Here!

Freedom

“On the 24th of February, far north in Europe, the tiny nation of Estonia celebrates its 102nd Independence Day. Cheers to the cleanest, greenest nation on earth! Happy Independence Day Estonia! Mu isamaa, mu õnn ja rõõm — My fatherland, my joy and happiness.” — Designed by Shishir Keluskar from Tallinn.

Freedom

Rock & Roll

Designed by Ricardo Gimenes from Sweden.

Rock & Roll

Celebrate Love

“February brings the season of love, and what could be better than celebrating it with Taj Mahal – the iconic monument and symbol of love.” — Designed by Farhat Asif from India.

Celebrate Love

Oldies But Goodies

Do you know those moments when you rediscover a treasured item you almost forgot about? Below you’ll find some February wallpaper goodies from our archives. Maybe one of your favorites from the past is in there, too? (Please note that these wallpapers don’t come with a calendar.)

Savannah Stroll

“February is a month focused on romance and as a southerner, I can’t think of a more romantic way to spend a day than strolling the historic moss-draped streets of Savannah, GA. Spending time sitting on a bench on one of the many beautiful squares, holding hands and people watching as you sip a cappuccino.” — Designed by Heather Ozee Designs from the United States.

Savannah Stroll

Principles Of Good Design

“The simplicity seen in the work of Dieter Rams which has ensured his designs from the 50s and 60s still hold a strong appeal.” — — Designed by Vinu Chaitanya from India.

Principles of Good Design- Dieter Rams

Dark Temptation

“A dark romantic feel, walking through the city on a dark and rainy night.” — Designed by Matthew Talebi from the United States.

Dark Temptation

Cold And Frost

“Frosts in Russia are very severe. Walking through the Park, I found these branches at the top and decided to capture the moment.” — Designed by Nikolay Belikov from Russia.

Cold And Frost

Love Is Worth Fighting For

— Designed by Maria Keller from Mexico.

Love Is Worth Fighting For

Share The Same Orbit!

“I prepared a simple and chill layout design for February called ‘Share The Same Orbit!’ which suggests to share the love orbit.” — Designed by Valentin Keleti from Romania.

Share The Same Orbit!

Charlie Chaplin

“I love street art, so I took a shot of this great graffiti of Charlie Chaplin with his inspirational quote that is even more true for this age: ‘Sometimes we think too much and feel to little’. He also said: ‘More than machinery, we need humanity; more than cleverness, we need kindness and gentleness. Without these qualities, life will be violent and all will be lost.” — Designed by Marija Zaric from Belgrade, Serbia.

Charlie Chaplin

Plucking At The Heart Strings

“Choose to embrace Valentine’s as a day to appreciate those who are special to you. The base of this wallpaper is ‘Plucking at the Heart Strings’, an original painting by Hayden Gigner.” — Designed by Adam Mezzatesta from the United Kingdom.

Plucking At The Heart Strings

February Ferns

— Designed by Nathalie Ouederni from France.

February Ferns

French Fries

— Designed by Doreen Bethge from Germany.

French Fries

Snowy Sunset

— Designed by Nathalie Croze from France.

Snowy Sunset

Balloons

— Designed by Xenia Latii from Germany.

Balloons

February’s Gift

“A leap year means we have one more day to cherish! Maybe use it to visit an old friend, or go somewhere new, but use it well! And the most important: have some fun!” — — Designed by Printsome.com from the United Kingdom.

February’s Gift

Made In Japan

“See the beautiful colors, precision, and the nature of Japan in one picture.” — — Designed by Fatih Yilmaz from the Netherlands.

Made In Japan

February Flowers

“A little bit of romance, a little bit of vintage: Happy Valentine’s Day this month!” — Designed by Kari Andresen from the United States.

Smashing Wallpaper - february 13

Love Angel Vader

“Valentine’s Day is coming? Noooooooooooo!” — — Designed by Ricardo Gimenes from Sweden.

Love Angel Vader

Febrewery

“I live in Madison, WI USA, which is famous for its breweries. Wisconsin even named their baseball team ‘The Brewers.’ If you like beer, brats, and lots of cheese, it’s the place for you!” — — Designed by Danny Gugger from the United States.

Febrewery

Free Your Mind

“People should have the right to believe and think what they want. They should be free in choosing their opinion. The wallpaper (especially the birds) reminds me of the great freedom we have in many countries of the world.” — — Designed by Daniela Faltz from Germany.

Free Your Mind

Frozen Worlds

“A view of 2 frozen planets, lots of blue tints.” — Designed by Rutger Berghmans from Belgium.

Smashing Wallpaper - february 13

Join In Next Month!

Thank you to all designers for their participation. Join in next month!

Sticky Table of Contents with Scrolling Active States

Say you have a two-column layout: a main column with content. Say it has a lot of content, with sections that requires scrolling. And let’s toss in a sidebar column that is largely empty, such that you can safely put a position: sticky; table of contents over there for all that content in the main column. A fairly common pattern for documentation.

Bramus Van Damme has a nice tutorial on all this, starting from semantic markup, implementing most of the functionality with HTML and CSS, and then doing the last bit of active nav enhancement with JavaScript.

For example, if you don’t click yourself down to a section (where you might be able to get away with :target styling for active navigation), JavaScript is necessary to tell where you are scrolled to an highlight the active navigation. That active bit is handled nicely with IntersectionObserver, which is, like, the perfect API for this.

Here’s that result:

CodePen Embed Fallback

It reminds me of a very similar demo from Hakim El Hattab he called Progress Nav. The design pattern is exactly the same, but Hakim’s version has this ultra fancy SVG path that draws itself along the way, indenting for sub nav. I’ll embed a video here:

That one doesn’t use IntersectionObserver, so if you want to hack on this, combine ’em!

The post Sticky Table of Contents with Scrolling Active States appeared first on CSS-Tricks.

How To Create A Card Matching Game Using Angular And RxJS

How To Create A Card Matching Game Using Angular And RxJS

How To Create A Card Matching Game Using Angular And RxJS

Anna Prenzel

2020-01-30T13:00:00+00:00 2020-01-31T00:09:20+00:00

Today, I’d like to focus on data streams resulting from click events on the user interface. The processing of such clickstreams is particularly useful for applications with an intensive user interaction where many events have to be processed. I’d also like to introduce you to RxJS a bit more; it’s a JavaScript library that can be used to express event handling routines compactly and concisely in a reactive style.

What Are We Building?

Learning games and knowledge quizzes are popular both for younger and older users. An example is the game “pair matching”, where the user has to find related pairs in a mixture of images and/or text snippets.

The animation below shows a simple version of the game: The user selects two elements on the left and right side of the playing field one after the other, and in any order. Correctly matched pairs are moved to a separate area of the playing field, while any wrong assignments are immediately dissolved so that the user has to make a new selection.

Screen capture of the learningl game “matching pairs”
A sneak peek of the game we’ll be creating today

In this tutorial, we will build such a learning game step by step. In the first part, we will build an Angular component that is just showing the playing field of the game. Our aim is that the component can be configured for different use cases and target groups — from an animal quiz up to a vocabulary trainer in a language learning app. For this purpose, Angular offers the concept of content projection with customizable templates, which we will make use of. To illustrate the principle, I will build two versions of the game (“game1” and “game2”) with different layouts.

In the second part of the tutorial, we will focus on reactive programming. Whenever a pair is matched, the user needs to get some sort of feedback from the app; it is this event handling that is realized with the help of the library RxJS.

1. Building An Angular Component For The Learning Game

How To Create The Basic Framework

First, let’s create a new project named “learning-app”. With the Angular CLI, you can do this with the command ng new learning-app. In the file app.component.html, I replace the pre-generated source code as follows:

<div style="text-align:center"> <h1>Learning is fun!</h1>
</div>

In the next step, the component for the learning game is created. I’ve named it “matching-game” and used the command ng generate component matching-game. This will create a separate subfolder for the game component with the required HTML, CSS and Typescript files.

As already mentioned, the educational game must be configurable for different purposes. To demonstrate this, I create two additional components (game1 and game2) by using the same command. I add the game component as a child component by replacing the pre-generated code in the file game1.component.html or game2.component.html with the following tag:

<app-matching-game></app-matching-game>

At first, I only use the component game1. In order to make sure that game 1 is displayed immediately after starting the application, I add this tag to the app.component.html file:

<app-game1></app-game1>

When starting the application with ng serve --open, the browser will display the message “matching-game works”. (This is currently the only content of matching-game.component.html.)

Now, we need to test the data. In the /app folder, I create a file named pair.ts where I define the class Pair:

export class Pair { leftpart: string; rightpart: string; id: number;
}

A pair object comprises two related texts (leftpart and rightpart) and an ID.

The first game is supposed to be a species quiz in which species (e.g. dog) have to be assigned to the appropriate animal class (i.e. mammal).

In the file animals.ts, I define an array with test data:

import { Pair } from './pair';
export const ANIMALS: Pair[] = [ { id: 1, leftpart: 'dog', rightpart: 'mammal'}, { id: 2, leftpart: 'blickbird', rightpart: 'bird'}, { id: 3, leftpart: 'spider', rightpart: 'insect'}, { id: 4, leftpart: 'turtle', rightpart: 'reptile' }, { id: 5, leftpart: 'guppy', rightpart: 'fish'},
];

The component game1 needs access to our test data. They are stored in the property animals. The file game1.component.ts now has the following content:

import { Component, OnInit } from '@angular/core';
import { ANIMALS } from '../animals';
@Component({ selector: 'app-game1', templateUrl: './game1.component.html', styleUrls: ['./game1.component.css']
})
export class Game1Component implements OnInit { animals = ANIMALS; constructor() { } ngOnInit() { }
}

The First Version Of The Game Component

Our next goal: The game component matching-game has to accept the game data from the parent component (e.g. game1) as input. The input is an array of “pair” objects. The user interface of the game should be initialized with the passed objects when starting the application.

Screen capture of the learningl game “matching pairs”

For this purpose, we need to proceed as follows:

  1. Add the property pairs to the game component using the @Input decorator.
  2. Add the arrays solvedPairs and unsolvedPairs as additional private properties of the component. (It is necessary to distinguish between already “solved” and “not yet solved” pairs.)
  3. When the application is started (see function ngOnInit) all pairs are still “unsolved” and are therefore moved to the array unsolvedPairs.
import { Component, OnInit, Input } from '@angular/core';
import { Pair } from '../pair';
@Component({ selector: 'app-matching-game', templateUrl: './matching-game.component.html', styleUrls: ['./matching-game.component.css']
}) export class MatchingGameComponent implements OnInit { @Input() pairs: Pair[]; private solvedPairs: Pair[] = []; private unsolvedPairs: Pair[] = []; constructor() { } ngOnInit() { for(let i=0; i<this.pairs.length; i++){ this.unsolvedPairs.push(this.pairs[i]); } }
}

Furthermore, I define the HTML template of the matching-game component. There are containers for the unsolved and solved pairs. The ngIf directive ensures that the respective container is only displayed if at least one unsolved or solved pair exists.

In the container for the unsolved pairs (class container unsolved), first all left (see the left frame in the GIF above) and then all right (see the right frame in the GIF) components of the pairs are listed. (I use the ngFor directive to list the pairs.) At the moment, a simple button is sufficient as a template.

With the template expression {{{pair.leftpart}} and {{{pair.rightpart}}}, the values of the properties leftpart and rightpart of the individual pair objects are queried when iterating the pair array. They are used as labels for the generated buttons.

The assigned pairs are listed in the second container (class container solved). A green bar (class connector) indicates that they belong together.

The corresponding CSS code of the file matching-game.component.css can be found in the source code at the beginning of the article.

<div id="game"> <div class="container unsolved" *ngIf="unsolvedPairs.length>0"> <div class="pair_items left"> <button *ngFor="let pair of unsolvedPairs" class="item"> {{pair.leftpart}} </button> </div> <div class="pair_items right"> <button *ngFor="let pair of unsolvedPairs" class="item"> {{pair.rightpart}} </button> </div> </div> <div class="container solved" *ngIf="solvedPairs.length>0"> <div *ngFor="let pair of solvedPairs" class="pair"> <button>{{pair.leftpart}}</button> <div class="connector"></div> <button>{{pair.rightpart}}</button> </div> </div>
</div>

In the component game1, the array animals is now bound to the pairs property of the component matching-game (one-way data binding).

<app-matching-game [pairs]="animals"></app-matching-game>

The result is shown in the image below.

Current state of the user interface
Current state of the user interface

Obviously, our matching game is not too difficult yet, because the left and right parts of the pairs are directly opposite each other. So that the pairing is not too trivial, the right parts should be mixed. I solve the problem with a self-defined pipe shuffle, which I apply to the array unsolvedPairs on the right side (the parameter test is needed later to force the pipe to be updated):

...
<div class="pair_items right"> <button *ngFor="let pair of unsolvedPairs | shuffle:test" class="item"> {{pair.rightpart}} </button> </div>
...

The source code of the pipe is stored in the file shuffle.pipe.ts in the app folder (see source code at the beginning of the article). Also note the file app.module.ts, where the pipe must be imported and listed in the module declarations. Now the desired view appears in the browser.

Extended Version: Using Customizable Templates To Allow An Individual Design Of The Game

Instead of a button, it should be possible to specify arbitrary template snippets to customize the game. In the file matching-game.component.html I replace the button template for the left and right side of the game with an ng-template tag. I then assign the name of a template reference to the property ngTemplateOutlet. This gives me two placeholders, which are replaced by the content of the respective template reference when rendering the view.

We are here dealing with the concept of content projection: certain parts of the component template are given from outside and are “projected” into the template at the marked positions.

When generating the view, Angular must insert the game data into the template. With the parameter ngTemplateOutletContext I tell Angular that a variable contextPair is used within the template, which should be assigned the current value of the pair variable from the ngFor directive.

The following listing shows the replacement for the container unsolved. In the container solved, the buttons have to be replaced by the ng-template tags as well.

<div class="container unsolved" *ngIf="unsolvedPairs.length>0">
<div class="pair_items left"> <div *ngFor="let pair of unsolvedPairs" class="item"> <ng-template [ngTemplateOutlet]="leftpart_temp" [ngTemplateOutletContext]="{contextPair: pair}"> </ng-template> </div> </div> <div class="pair_items right"> <div *ngFor="let pair of unsolvedPairs | shuffle:test" class="item"> <ng-template [ngTemplateOutlet]="leftpart_temp" [ngTemplateOutletContext]="{contextPair: pair}"> </ng-template> </div>
</div>
</div>
...

In the file matching-game.component.ts, the variables of both template references (leftpart_temp and rightpart_temp) must be declared. The decorator @ContentChild indicates that this is a content projection, i.e. Angular now expects that the two template snippets with the respective selector (leftpart or rightpart) are provided in the parent component between the tags <app-matching-game></app-matching-game> of the host element (see @ViewChild).

@ContentChild('leftpart', {static: false}) leftpart_temp: TemplateRef<any>;
@ContentChild('rightpart', {static: false}) rightpart_temp: TemplateRef<any>;

Don’t forget: The types ContentChild and TemplateRef must be imported from the core package.

In the parent component game1, the two required template snippets with the selectors leftpart and rightpart are now inserted.

For the sake of simplicity, I will reuse the buttons here again:

<app-matching-game [pairs]="animals"> <ng-template #leftpart let-animalPair="contextPair"> <button>{{animalPair.leftpart}}</button> </ng-template> <ng-template #rightpart let-animalPair="contextPair"> <button>{{animalPair.rightpart}}</button> </ng-template>
</app-matching-game>

The attribute let-animalPair="contextPair" is used to specify that the context variable contextPair is used in the template snippet with the name animalPair.

The template snippets can now be changed to your own taste. To demonstrate this I use the component game2. The file game2.component.ts gets the same content as game1.component.ts. In game2.component.html I use an individually designed div element instead of a button. The CSS classes are stored in the file game2.component.css.

<app-matching-game [pairs]="animals"> <ng-template #leftpart let-animalPair="contextPair"> <div class="myAnimal left">{{animalPair.leftpart}}</div> </ng-template> <ng-template #rightpart let-animalPair="contextPair"> <div class="myAnimal right">{{animalPair.rightpart}}</div> </ng-template>
</app-matching-game>

After adding the tags <app-game2></app-game2> on the homepage app.component.html, the second version of the game appears when I start the application:

An alternative view of the game in the component game2
An alternative view of the game in the component game2

The design possibilities are now almost unlimited. It would be possible, for example, to define a subclass of Pair that contains additional properties. For example, image addresses could be stored for the left and/or right parts. The images could be displayed in the template along with the text or instead of the text.

2. Control Of User Interaction With RxJS

Advantages Of Reactive Programming With RxJS

To turn the application into an interactive game, the events (e.g. mouse click events) that are triggered at the user interface must be processed. In reactive programming, continuous sequences of events, so-called “streams”, are considered. A stream can be observed (it is an “observable”), i.e. there can be one or more “observers” or “subscribers” subscribing to the stream. They are notified (usually asynchronously) about every new value in the stream and can react to it in a certain way.

With this approach, a low level of coupling between the parts of an application can be achieved. The existing observers and observables are independent of each other and their coupling can be varied at runtime.

The JavaScript library RxJS provides a mature implementation of the Observer design pattern. Furthermore, RxJS contains numerous operators to convert streams (e.g. filter, map) or to combine them into new streams (e.g. merge, concat). The operators are “pure functions” in the sense of functional programming: They do not produce side effects and are independent of the state outside the function. A program logic composed only of calls to pure functions does not need global or local auxiliary variables to store intermediate states. This, in turn, promotes the creation of stateless and loosely coupled code blocks. It is therefore desirable to realize a large part of the event handling by a clever combination of stream operators. Examples of this are given in the section after next, based on our matching game.

Integrating RxJS Into The Event Handling Of An Angular Component

The Angular framework works with the classes of the RxJS library. RxJS is therefore automatically installed when Angular is installed.

The image below shows the main classes and functions that play a role in our considerations:

A model of the essential classes for event handling in Angular/RxJS
A model of the essential classes for event handling in Angular/RxJS
Class NameFunction
Observable (RxJS)Base class that represents a stream; in other words, a continuous sequence of data. An observable can be subscribed to. The pipe function is used to apply one or more operator functions to the observable instance.
Subject (RxJS)The subclass of observable provides the next function to publish new data in the stream.
EventEmitter (Angular)This is an angular-specific subclass that is usually only used in conjunction with the @Output decorator to define a component output. Like the next function, the emit function is used to send data to the subscribers.
Subscription (RxJS)The subscribe function of an observable returns a subscription instance. It is required to cancel the subscription after using the component.

With the help of these classes, we want to implement the user interaction in our game. The first step is to make sure that an element that is selected by the user on the left or right side is visually highlighted.

The visual representation of the elements is controlled by the two template snippets in the parent component. The decision how they are displayed in the selected state should therefore also be left to the parent component. It should receive appropriate signals as soon as a selection is made on the left or right side or as soon as a selection is to be undone.

For this purpose, I define four output values of type EventEmitter in the matching-game.component.ts file. The types Output and EventEmitter have to be imported from the core package.

@Output() leftpartSelected = new EventEmitter<number>();
@Output() rightpartSelected = new EventEmitter<number>();
@Output() leftpartUnselected = new EventEmitter();
@Output() rightpartUnselected = new EventEmitter();

In the template matching-game.component.html, I react to the mousedown event on the left and right side, and then send the ID of the selected item to all receivers.

<div *ngFor="let pair of unsolvedPairs" class="item" (mousedown)="leftpartSelected.emit(pair.id)">
...
<div *ngFor="let pair of unsolvedPairs | shuffle:test" class="item" (mousedown)="rightpartSelected.emit(pair.id)">

In our case, the receivers are the components game1 and game2. There you can now define the event handling for the events leftpartSelected, rightpartSelected, leftpartUnselected and rightpartUnselected. The variable $event represents the emitted output value, in our case the ID. In the following you can see the listing for game1.component.html, for game2.component.html the same changes apply.

<app-matching-game [pairs]="animals" (leftpartSelected)="onLeftpartSelected($event)" (rightpartSelected)="onRightpartSelected($event)" (leftpartUnselected)="onLeftpartUnselected()" (rightpartUnselected)="onRightpartUnselected()"> <ng-template #leftpart let-animalPair="contextPair"> <button [class.selected]="leftpartSelectedId==animalPair.id"> {{animalPair.leftpart}} </button> </ng-template> <ng-template #rightpart let-animalPair="contextPair"> <button [class.selected]="rightpartSelectedId==animalPair.id"> {{animalPair.rightpart}} </button> </ng-template>
</app-matching-game>

In game1.component.ts (and similarly in game2.component.ts), the event handler functions are now implemented. I store the IDs of the selected elements. In the HTML template (see above), these elements are assigned the class selected. The CSS file game1.component.css defines which visual changes this class will bring about (e.g. color or font changes). Resetting the selection (unselect) is based on the assumption that the pair objects always have positive IDs.

onLeftpartSelected(id:number):void{ this.leftpartSelectedId = id;
}
onRightpartSelected(id:number):void{ this.rightpartSelectedId = id;
}
onLeftpartUnselected():void{ this.leftpartSelectedId = -1;
}
onRightpartUnselected():void{ this.rightpartSelectedId = -1;
}

In the next step, event handling is required in the matching game component. It must be determined if an assignment is correct, that is, if the left selected element matches the right selected element. In this case, the assigned pair can be moved into the container for the resolved pairs.

I would like to formulate the evaluation logic using RxJS operators (see the next section). For preparation, I create a subject assignmentStream in matching-game.component.ts. It should emit the elements selected by the user on the left or right side. The goal is to use RxJS operators to modify and split the stream in such a way that I get two new streams: one stream solvedStream which provides the correctly assigned pairs and a second stream failedStream which provides the wrong assignments. I would like to subscribe to these two streams with subscribe in order to be able to perform appropriate event handling in each case.

I also need a reference to the created subscription objects, so that I can cancel the subscriptions with “unsubscribe” when leaving the game (see ngOnDestroy). The classes Subject and Subscription must be imported from the package “rxjs”.

private assignmentStream = new Subject(); private solvedStream = new Observable<Pair>();
private failedStream = new Observable<string>(); private s_Subscription: Subscription;
private f_Subscription: Subscription; ngOnInit(){ ... //TODO: apply stream-operators on //leftpartClicked und rightpartClicked this.s_Subscription = this.solvedStream.subscribe(pair => handleSolvedAssignment(pair)); this.f_Subscription = this.failedStream.subscribe(() => handleFailedAssignment());
} ngOnDestroy() { this.s_Subscription.unsubscribe(); this.f_Subscription.unsubscribe();
}

If the assignment is correct, the following steps are done:

  • The assigned pair is moved to the container for the solved pairs.
  • The events leftpartUnselected and rightpartUnselected are sent to the parent component.

No pair is moved if the assignment is incorrect. If the wrong assignment was executed from left to right (side1 has the value left), the selection should be undone for the element on the left side (see the GIF at the beginning of the article). If an assignment is made from right to left, the selection is undone for the element on the right side. This means that the last element that was clicked on remains in a selected state.

For both cases, I prepare the corresponding handler functions handleSolvedAssignment and handleFailedAssignment (remove function: see source code at the end of this article):

private handleSolvedAssignment(pair: Pair):void{ this.solvedPairs.push(pair); this.remove(this.unsolvedPairs, pair); this.leftpartUnselected.emit(); this.rightpartUnselected.emit(); //workaround to force update of the shuffle pipe this.test = Math.random() * 10;
}
private handleFailedAssignment(side1: string):void{ if(side1=="left"){ this.leftpartUnselected.emit(); }else{ this.rightpartUnselected.emit(); } }

Now we have to change the viewpoint from the consumer who subscribes to the data to the producer who generates the data. In the file matching-game.component.html, I make sure that when clicking on an element, the associated pair object is pushed into the stream assignmentStream. It makes sense to use a common stream for the left and right side because the order of the assignment is not important for us.

<div *ngFor="let pair of unsolvedPairs" class="item" (mousedown)="leftpartSelected.emit(pair.id)"
(click)="assignmentStream.next({pair: pair, side: 'left'})">
...
<div *ngFor="let pair of unsolvedPairs | shuffle:test" class="item" (mousedown)="rightpartSelected.emit(pair.id)" (click)="assignmentStream.next({pair: pair, side: 'right'})">

Design Of The Game Interaction With RxJS Operators

All that remains is to convert the stream assignmentStream into the streams solvedStream and failedStream. I apply the following operators in sequence:

pairwise

There are always two pairs in an assignment. The pairwise operator picks the data in pairs from the stream. The current value and the previous value are combined into a pair.

From the following stream…

„{pair1, left}, {pair3, right}, {pair2, left}, {pair2, right}, {pair1, left}, {pair1, right}“

…results this new stream:

„({pair1, left}, {pair3, right}), ({pair3, right}, {pair2, left}), ({pair2, left}, {pair2, right}), ({pair2, right}, {pair1, left}), ({pair1, left}, {pair1, right})“ 

For example, we get the combination ({pair1, left}, {pair3, right}) when the user selects dog (id=1) on the left side and insect (id=3) on the right side (see array ANIMALS at the beginning of the article). These and the other combinations result from the game sequence shown in the GIF above.

filter

You have to remove all combinations from the stream that were made on the same side of the playing field like ({pair1, left}, {pair1, left}) or ({pair1, left}, {pair4, left}).

The filter condition for a combination comb is therefore comb[0].side != comb[1].side.

partition

This operator takes a stream and a condition and creates two streams from this. The first stream contains the data that meets the condition and the second stream contains the remaining data. In our case, the streams should contain correct or incorrect assignments. So the condition for a combination comb is comb[0].pair===comb[1].pair.

The example results in a „correct” stream with

({pair2, left}, {pair2, right}), ({pair1, left}, {pair1, right}) 

and a “wrong” stream with

({pair1, left}, {pair3, right}), ({pair3, right}, {pair2, left}), ({pair2, right}, {pair1, left}) 

map

Only the individual pair object is required for further processing of a correct assignment, such as pair2. The map operator can be used to express that the combination comb should be mapped to comb[0].pair. If the assignment is incorrect, the combination comb is mapped to the string comb[0].side because the selection should be reset on the side specified by side.

The pipe function is used to concatenate the above operators. The operators pairwise, filter, partition, map must be imported from the package rxjs/operators.

ngOnInit() { ... const stream = this.assignmentStream.pipe( pairwise(), filter(comb => comb[0].side != comb[1].side) ); //pipe notation leads to an error message (Angular 8.2.2, RxJS 6.4.0) const [stream1, stream2] = partition(comb => comb[0].pair === comb[1].pair)(stream); this.solvedStream = stream1.pipe( map(comb => comb[0].pair) ); this.failedStream = stream2.pipe( map(comb => comb[0].side) ); this.s_Subscription = this.solvedStream.subscribe(pair => this.handleSolvedAssignment(pair)); this.f_Subscription = this.failedStream.subscribe(side => this.handleFailedAssignment(side));
}

Now the game already works!

Screen capture of the learningl game “matching pairs”
Final result

By using the operators, the game logic could be described declaratively. We only described the properties of our two target streams (combined into pairs, filtered, partitioned, remapped) and did not have to worry about the implementation of these operations. If we had implemented them ourselves, we would also have had to store intermediate states in the component (e.g. references to the last clicked items on the left and right side). Instead, the RxJS operators encapsulate the implementation logic and the required states for us and thus raise the programming to a higher level of abstraction.

Conclusion

Using a simple learning game as an example, we tested the use of RxJS in an Angular component. The reactive approach is well suited to process events that occur on the user interface. With RxJS, the data needed for event handling can be conveniently arranged as streams. Numerous operators, such as filter, map or partition are available for transforming the streams. The resulting streams contain data that is prepared in its final form and can be subscribed to directly. It requires a little skill and experience to select the appropriate operators for the respective case and to link them efficiently. This article should provide an introduction to this.

Further Resources

Related Reading on SmashingMag:

Smashing Editorial (ra, il)
20 Freshest Web Designs, January 2020

January 2020 is picking up where 2019 left off, with lots of animation and even more bold, bright color schemes. We’re also seeing an unusual number of luxury sites this month, and as always there’s a strong set of startups trying to break into the market. Enjoy!

Plink

To take on giants like PayPal, you need a compelling brand and a simple message, that can also wow with its first impression. Plink hits the nail on the head with its 3D animation.

Madame Turfu

Are you wondering what 2020 will hold for you? Why wait to find out when Madame Turfu can predict the future with this wonderfully fun set of digital tarot cards.

Nathan Taylor

What’s not to love about Nathan Taylor’s playful site? There’s so much to explore and do, but our favorite part is the different lighting modes.

Meatable

Selling Meatable is a tough prospect; it’s real meat, grown in a lab instead of taken by animal slaughter. The simple step-by-step site does a great job of explaining.

Sussex Royal

Whatever your view of Harry and Megan, there’s little doubt that their website oozes class. For a promotional site that isn’t actually selling anything, it’s a strong presence.

Emotive Feels

This fantastic manifesto from design agency Emotive Brand illustrates an A–Z of potential brand emotions with simple animations that would grace the cover of a Bluenote release.

UN\REAL

Swiss design agency UN\REAL’s site is a wonderfully chaotic love affair with web animation. It’s the type of site we can click around for hours, enjoying the sharp transitions.

Kate Jackling

Sometimes the best design takes a step back and allows its subject to bask in all the attention. Kate Jackling’s site does this, letting her gorgeous photography take center stage.

Helias

Helias has fully embraced the blob trend with a flood-filled area of color supporting each of its various products. It’s appropriate, engaging, and breaks up the formal grid well.

Klokki

Sometimes the hardest sites to design, are the ones for products about which there’s very little to say. Klokki is one such product, but its site is bold, confident, and persuasive.

Jonnie Hallman

Jonnie Hallman’s simple résumé site benefits greatly from the household names he’s worked for. We really like the details, like the way the monogram changes color as you scroll.

eaast

eaast is a design and development partnership from Paris that’s fully embraced the Memphis style. Their simple site proves you don’t need years’ worth of work to sell yourself.

Pantheone Audio

Proving that elegant scrolling is still very much a thing in 2020, Pantheone Audio uses the scroll to seamlessly navigate a luxurious site with a complex grid underpinning it.

Leaf

After decades of the best a man can get, the half of the species that shaves daily seems to be obsessed with reinventing the process. Leaf taps into that simple marketing approach.

Mociun

Most sites that sell jewelry miss the spirit of the pieces by focusing on the financial value. Mocuin gets it right with an on-trend color palette and stunning product photography.

Jon Way

Jon Way’s portfolio features work from over a decade of art direction. There’s a clear, consistent aesthetic thanks to a lovely ‘static’ effect that plays across the whole site.

Kota Yamaji

There’s some amazing work in Kato Yamaji’s portfolio, but what really strikes home is the amount of color he manages to squeeze in.

Robb Owen

We’ve seen lots of animated vector avatars over the last couple of years, but rarely do we see one with as much personality as Robb Owen’s. The cursor tracking makes it feel real.

Glasgow International Festival 2020

The Glasgow International Festival takes place between 24th April and 10th May 2020. Its site features some distinctly celtic typography, and tons of bold color.

Megababe

Megababe is taking on the beauty industry with a range of body products that are insanely popular, and as positive as its super-confident sales site.

Source
p img {display:inline-block; margin-right:10px;}
.alignleft {float:left;}
p.showcase {clear:both;}
body#browserfriendly p, body#podcast p, div#emailbody p{margin:0;}

How Do You Do max-font-size in CSS?

CSS doesn’t have max-font-size, so if we need something that does something along those lines, we have to get tricky.

Why would you need it at all? Well, font-size itself can be set in dynamic ways. For example, font-size: 10vw;. That’s using “viewport units” to size the type, which will get larger and smaller with the size of the browser window. If we had max-font-size, we could limit how big it gets (similarly the other direction with min-font-size).

One solution is to use a media query at a certain screen size breakpoint that sets the font size in a non-relative unit.

body { font-size: 3vw;
}
@media screen and (min-width: 1600px) { body { font-size: 30px; }
}

There is a concept dubbed CSS locks that gets fancier here, slowly scaling a value between a minimum and maximum. We’ve covered that. It can be like…

body { font-size: 16px;
}
@media screen and (min-width: 320px) { body { font-size: calc(16px + 6 * ((100vw - 320px) / 680)); }
}
@media screen and (min-width: 1000px) { body { font-size: 22px; }
}

We’ve also covered how it’s gotten (or will get) a lot simpler.

There is a max() function in CSS, so our example above becomes a one-liner:

font-size: max(30vw, 30px);

Or double it up with a min and max:

font-size: min(max(16px, 4vw), 22px);

Which is identical to:

font-size: clamp(16px, 4vw, 22px);

Browser compatibility for these functions is pretty sparse as I’m writing this, but Chrome currently has it. It will get there, but look at the first option in this article if you need it right now.

Now that we have these functions, it seems unlikely to me we’ll ever get min-font-size and max-font-size in CSS, since the functions are almost more clear as-is.

The post How Do You Do max-font-size in CSS? appeared first on CSS-Tricks.

Using CSCS Scripting Language For Cross-Platform Development

Using CSCS Scripting Language For Cross-Platform Development

Using CSCS Scripting Language For Cross-Platform Development

Vassili Kaplan

2020-01-29T11:00:00+00:00 2020-01-29T23:36:36+00:00

Our goal is not to build a platform; it’s to be cross all of them.

— Mark Zuckerberg

CSCS (Customized Scripting in C#) is an open-source scripting language implemented in C#. Syntactically it’s very similar to JavaScript, but it also has some similarities with Python. Some of these similarities are the keywords in the well-known if…elif…else construct, and also have the same variable scope definition as in Python (e.g. a variable defined inside of an if block or inside a loop will be also visible outside).

As opposed to JavaScript and Python, variables and functions in CSCS are case-insensitive. The primary goal of CSCS is to let the developer write as little code as possible. Also, the same code is used for both iOS and Android development. Additionally, CSCS can be used for Windows, Mac, and Unity development.

Note: You can read more about how Microsoft uses CSCS in their Maquette product (based on Unity) over here.

CSCS can be added to your project by embedding its C# source code into a Visual Studio Xamarin project. Unlike most other languages, you have full ownership of the CSCS source code and can easily add or modify its functionality. I’ll be sharing an example of this later on in the article.

Also, we are going to learn how to get started with CSCS and use some more advanced features that have been covered in other articles. Among these features, we are going to access a Web Service via Web Requests with JSON string parsing, and we’ll also be using SQLite on iOS and Android.

The easiest way to get started is to download a sample of a project using CSCS and start playing with the start.cscs file. This is what we’ll be doing in the next section: creating an iOS/Android app with basic GUI and events.

“Hello, World!” In CSCS

Let’s start with a relatively simple example of CSCS code that constructs a screen with a few widgets:

AutoScale();
SetBackgroundColor("light_green"); locLabelText = GetLocation("ROOT", "CENTER", "ROOT", "TOP");
AddLabel(locLabelText, "labelText", "Welcome " + _DEVICE_INFO_ + " " + _VERSION_INFO_ + " User!", 600, 100); locTextEdit = GetLocation("ROOT", "LEFT", labelText, "BOTTOM");
AddTextEdit(locTextEdit, "textEdit", "Your name", 320, 80); locButton = GetLocation(textEdit,"RIGHT",textEdit, "CENTER");
AddButton(locButton, "buttonHi", "Hello", 160, 80); function buttonHi_click(sender, arg) { name = getText(textEdit); msg = name != "" ? "Hello, "+ name + "!" : "Hello, World!"; AlertDialog("My Great App", msg);
}

The image below shows the resulting user interface on an iPhone as well as an Android device after clicking on the “Hello” button and not typing anything in the “Text Edit” field:

Hello, World!” on iPhone (left) and Android (right)
“Hello, World!” on iPhone (left) and Android (right) (Large preview)

Let’s briefly go over the code above. It starts with the AutoScale() function call, and what that does is to tell the parser that the widget sizes are relative to the screen size, i.e. they will be auto-resized (the widget will look bigger on bigger screens and smaller on smaller screens). This setting could be also overridden per widget.

Note that there is no need to create a special handler on a button click. If you define a function with name widgetName_click(), it will be used as a handler when the user clicks on a widget called widgetName (it doesn’t have to be a button, it can actually be any widget). That’s why the function buttonHi_click() will be triggered as soon as the user clicks on the button.

You may have noticed that the GUI is constructed completely in code. This is done by supplying a relative widget location when adding it. The general format of a location command is the following:

location = GetLocation(WidgetX, HorizontalPlacement, WidgetY, VerticalPlacement, deltaX=0, deltaY=0, autoResize=true);

So, you can place a widget relative to other widgets on the screen. A special case of a widget is a “ROOT” widget, meaning the main screen.

After creating a location, you need to provide it as an argument to any of the following functions:

  • AddLabel,
  • AddButton,
  • AddCombobox,
  • AddStepper,
  • AddListView,
  • AddTextView,
  • AddStepper,
  • AddImageView,
  • AddSlider,
  • AddPickerView,
  • and so on.

All of the above have the same structure:

AddButton(location, newWidgetname, initialValue, width, height);

The widget width and height will be relative to the screen size if the AutoScale() CSCS command was previously run. Also, the initial value (in case of a button) is the text shown on it. This can be changed anytime by invoking SetText(widgetName, newText).

Using Visual Studio Code To Debug CSCS

We can also use Visual Studio Code to debug CSCS scripts. If you want to develop apps for both Android and iOS, you need to use a Mac. After installing Visual Studio Code, install the CSCS Debugger and REPL extension.

In order to use the extension, add this line of code anywhere in your start.cscs CSCS script:

StartDebugger();

The following image below shows how you can use Visual Studio Code to debug and change the functionality of the “Hello, World!” app that we developed in the previous section. In the upcoming example, we’ll be adding a label and a button on the fly to the existing layout.

To do this, we just select the code to be executed by the parser and press Ctrl + 8. As a result, a label and a button will be added at the center of the screen. We also add a button handler that will update the new label with the current time on each button click.

Changing Layout on the fly with Visual Studio Code
Changing Layout on the fly with Visual Studio Code (Large preview)

Using SQLite In CSCS

SQLite is an ACID (Atomicity, Consistency, Isolation, Durability) type of a relational database, and was developed by Richard Hipp (the first version was released in 2000). In difference to other relational databases, like Microsoft SQL Server or Oracle Database, it’s embedded. (Embedded not only into the device, but also into the end program.) It’s included in the program as a very compact library, which is less than 500 KB in size. But two apps (released by the same developer) can read the same SQLite DB if the DB file path is known to both apps.

The advantage of SQLite is that it can be used without an extra installation on an iOS or an Android device. The disadvantage is that it obviously cannot hold as much data as a “normal” DB and also that it’s weakly typed (i.e. you can insert a string instead of an integer — it will then be converted to an integer or 0 on failure). On the other hand, the latter can be also seen as an advantage as well.

SQLite can be easily used from CSCS without extra import statements. Here’s a table that will help you get an overview of the main SQLite functions used in CSCS:

CommandDescription
SQLInit(DBName)Initializes a database or sets a database to be used with consequent DB statements.
SQLDBExists(DBName)Checks whether the DB has been initialized. Also sets the database to be used with consequent DB statements.
SQLQuery(query)Executes an SQL query (a select statement). Returns a table with records.
SQLNonQuery(nonQuery)Executes an SQL non-query, e.g. an update, create or delete statement. Returns number of records affected.
SQLInsert(tableName, columnList, data)Inserts passed table of data of records to the specified DB table. The columnList argument has the following structure: colName1,colName2,…,colNameN

Table 1: SQLite commands in CSCS

This is how the SQLInit() and SQLDBExists() functions are typically used:

DBName = "myDB.db1"; if (!SQLDBExists(DBName)) { create = "CREATE TABLE [Data] (Symbol ntext, Low real, High real, Close real, Volume real, Stamp text DEFAULT CURRENT_TIMESTAMP)"; SQLNonQuery(create);
} SQLInit(DBName);

We are going to see more examples of how you can select and insert data into an SQLite database later on. I’ll show you an example of how to write stock data that has been extracted from a Web Service into a local SQLite database.

Adding Custom Functionality To CSCS

In this section, we are going to see how you can extend the CSCS functionality. As an example, we are going to see the existing implementation of the CSCS Sleep function below.

To add custom functionality, all you need to do is create a new class by deriving from the ParserFunction class, overriding its Evaluate() method, and registering this class with the parser. Here’s a short version (without error checking):

class SleepFunction : ParserFunction
{ protected override Variable Evaluate(ParsingScript script) { List  args = script.GetFunctionArgs(); int sleepms = Utils.GetSafeInt(args, 0); Thread.Sleep(sleepms); return Variable.EmptyInstance; }
}

Registration of a class with the parser can be done anywhere in the initialization stage via the following command:

ParserFunction.RegisterFunction("Sleep", new SleepFunction());

That’s it! Now the Evaluate() method of the SleepFunction class will be invoked as soon as a “Sleep” token is extracted by the parser.

Note that CSCS is case insensitive (except the core control flow statements: if, elif, else, for, while, function, include, new, class, return, try, throw, catch, break, continue). This means that you can type either “sleep(100)” or “Sleep(100)” — both calls will suspend the executing thread for 100 milliseconds.

Processing JSON In CSCS

JSON (JavaScript Object Notation) is a lightweight data interchange format, consisting of attribute-value pairs and array-type pairs. It was developed by Douglas Crockford in the early 2000s (around same time when SQLite appeared as well).

In this section, we are going to learn how to parse JSON using CSCS.

The CSCS function to parse a JSON string is GetVariableFromJSON(jsonText). This function returns a hash table in which the keys are the attributes from the JSON string.

Consider the following example of a JSON string:

jsonString = '{ "eins" : 1, "zwei" : "zweiString", "mehr" : { "uno": "dos" }, "arrayValue" : [ "une", "deux" ] }';

After invoking:

a = GetVariableFromJSON();

The variable a will be a hash table with the following values:

a["eins"] = 1
a["zwei"] = "zweiString"
a["mehr"]["uno"] = "dos"
a["arrayValue"][0] = "une"
a["arrayValue"][1] = "deux"

In the next section, we are going to see another example of parsing a JSON string from a Web Service.

An Example Of An App With SQLite, Web Requests And JSON

For an app using SQLite, a Web Service and JSON parsing, we are going to use Alpha Vantage Web Service. You can get an API Key for free but the free version allows accessing their web service no more than 5 times per minute.

Using Alpha Vantage, you can extract various financial data sets — including stock prices. This is what we are going to do in our sample app.

The image below shows how the Stocks apps looks on an iOS and on an Android device.

Extracting Stocks from Alpha Vantage Web Service on iOS (left) and Android (right)
Extracting Stocks from Alpha Vantage Web Service on iOS (left) and Android (right) (Large preview)

The CSCS code to build the GUI is the following:

locLabel = GetLocation("ROOT","CENTER", "ROOT","TOP", 0,30);
AddLabel(locLabel, "labelRefresh", "", 480, 60); locSFWidget = GetLocation("ROOT","CENTER", labelRefresh,"BOTTOM");
AddSfDataGrid(locSFWidget, "DataGrid", "", graphWidth, graphHeight); listCols = {"Symbol","string", "Low","number", "High", "number", "Close","number", "Volume","number"};
AddWidgetData(DataGrid, listCols, "columns");
colWidth = {17, 19, 19, 19, 26};
AddWidgetData(DataGrid, colWidth, "columnWidth"); locButton = GetLocation("ROOT","CENTER",DataGrid,"BOTTOM");
AddButton(locButton, "buttonRefresh", "Refresh", 160, 80); locLabelError = GetLocation("ROOT","CENTER","ROOT","BOTTOM");
AddLabel(locLabelError, "labelError", "", 600, 160);
SetFontColor(labelError, "red");
AlignText(labelError, "center"); getDataFromDB();

The getDataFromDB() method will extract all the data from the SQLite database. It uses the SQL query defined as follows:

query = "SELECT Symbol, Low, High, Close, Volume, DATETIME(Stamp, 'localtime') as Stamp FROM Data ORDER BY Stamp DESC LIMIT 5;";

Take a look at the code below for the getDataFromDB() implementation.

function getDataFromDB() { results = SQLQuery(query); for (i = 1; i < results.Size; i++) { vals = results[i]; stock = vals[0]; low = Round(vals[1], 2); high = Round(vals[2], 2); close = Round(vals[3], 2); volume = Round(vals[4], 2); refresh = vals[5]; stockData = {stock, low, high, close, volume}; AddWidgetData(DataGrid, stockData, "item"); } SetText(labelRefresh, "DB Last Refresh: " + refresh); lockGui(false);
}

Now let’s see how we get data from the Alpha Vantage Web Service. First, we initialize the data:

baseURL = "https://www.alphavantage.co/query? " + "function=TIME_SERIES_DAILY&symbol=";
apikey = "Y12T0TY5EUS6BC5F";
stocks = {"MSFT", "AAPL", "GOOG", "FB", "AMZN"};
totalStocks = stocks.Size;

Next, we load stocks one by one as soon as the user clicks on the “Refresh” button:

function buttonRefresh_click(object, arg) { lockGui(); SetText(labelRefresh, "Loading ..."); SetText(labelError, ""); ClearWidget(DataGrid); loadedStocks = 0; getData(stocks[loadedStocks]);
} function getData(symbol) { stockUrl = baseURL + symbol + "&apikey=" + apikey; WebRequest("GET", stockUrl, "", symbol, "OnSuccess", "OnFailure");
}

Here’s the main CSCS function to use in order to get data from a Web Service:

WebRequest("GET", stockUrl, "", symbol, "OnSuccess", "OnFailure");

The last two parameters are functions to invoke on completion of the web request. For example, in case of a failure, the following CSCS function will be called:

function OnFailure(object, errorCode, text)
{ SetText(labelError, text); lockGui(false);
}

As a result, the user will get an error message as shown below:

An error when requesting web data
An error when requesting web data (Large preview)

But, if all is good, we are going to parse the JSON string and insert its contents into the SQLite DB.

function OnSuccess(object, errorCode, text)
{ jsonFromText = GetVariableFromJSON(text); metaData = jsonFromText[0]; result = jsonFromText[1]; symbol = metaData["2. Symbol"]; lastRefreshed = metaData["3. Last Refreshed"]; allDates = result.keys; dateData = result[allDates[0]]; high = Round(dateData["2. high"], 2); low = Round(dateData["3. low"], 2); close = Round(dateData["4. close"], 2); volume = dateData["5. volume"]; stockData = {symbol, low, high, close, volume}; SQLInsert("Data","Symbol,Low,High,Close,Volume",stockData); if (++loadedStocks >= totalStocks) { getDataFromDB(); } else { getData(stocks[loadedStocks]); }
}

In order to understand how we access different fields in the hash table above, let’s take a look at the actual string received from the Alpha Vantage web request:

{ "Meta Data": { "1. Information": "Daily Prices (open, high, low, close) and Volumes", "2. Symbol": "MSFT", "3. Last Refreshed": "2019-10-02 14:23:20", "4. Output Size": "Compact", "5. Time Zone": "US/Eastern" }, "Time Series (Daily)": { "2019-10-02": { "1. open": "136.3400", "2. high": "136.3700", "3. low": "133.5799", "4. close": "134.4100", "5. volume": "11213086" }, … }
}

As you can see, we get the latest date as the first element of the allDates array that consists all of the extracted dates.

Conclusion

Adding CSCS to your project is easy. All you need to do is simply embed the source code of CSCS as a module to your project — just like it’s done in a sample Xamarin project.

Do you use and extend CSCS scripting language in your projects? Leave a comment below — I’d be happy to hear from you!

Further Reading

If you want to explore the CSCS language a bit more, here are some of the articles I’ve written about on the topic:

As an additional resource, I also recommend reading how you can improve CSCS performance by precompiling its functions.

Smashing Editorial (ra, yk, il)
Use and Reuse Everything in SVG… Even Animations!

If you are familiar with SVG and CSS animations and started to work with them often, here are some ideas you might want to keep in mind before jumping into the job. This article will be about learning how to build and optimize your code with <use> element, CSS Variables and CSS animations.

Live Demo

Part 1: The SVG <use> element

If you are a developer that likes to keep your code DRY or a big fan of Sass/CSS variables, there is a good chance that you will like this tag.

Let’s say you have an element that is repeated many times in your graphic. Instead of having a complex part of your code repeated many times in your SVG, you can define this part once and then clone it somewhere else in your document with the <use> element. This will not only reduce an enormous amount of code, but also will make your markup simpler and easier to manipulate.

To start implementing the <use> element, go to your SVG and follow this steps:

  1. Identify the part of the code that you want to clone
  2. Add an ID to that part
  3. Link it inside your <use> tag like this: <use xlink:href="#id"/>

That’s it! Your new clone is ready, now you can change its attributes (e.g. x and y position) to fit your needs.

Let’s dive into a very convenient example

I want to share this real case where I needed to animate a big cube made of little cube units. (Imagine the classic Rubik’s Cube.)

We’ll start by drawing the cube unit in SVG using basic shapes and transforms:

<svg viewBox="-130 -20 300 100"> <g id="cube"> <rect width="21" height="24" transform="skewY(30)"/> <rect width="21" height="24" transform="skewY(-30) translate(21 24.3)"/> <rect width="21" height="21" transform="scale(1.41,.81) rotate(45) translate(0 -21)"/> </g>
</svg>
CodePen Embed Fallback

Note that the shapes are grouped in a <g> element so we can add the ID to the whole figure.

Next, let’s build a bigger cube cloning this unit. First, we need to wrap the cube from the previous example inside the <defs> tag inside the SVG. In the <defs> element we can put whatever we want to reuse, which could be a single shape, a group, a gradient.. almost any SVG element. They won’t render anywhere unless we use them outside this tag.

Then we can link the unit as many times as we want using its ID and change the x and y position on every clone like this:

<use xlink:href="#cube" x="142" y="124"/>
<use xlink:href="#cube" x="100" y="124"/>
<!-- ... -->
CodePen Embed Fallback

Now we have to position every cube remembering that the last element will appear at the front, after that we’ll have our first big cube ready!

xlink:href is deprecated since SVG2, but is better to use it for compatibility purposes. In modern browsers you can just use href but I tested it on Safari and at the time of writing is not working there. If you use xlink:href make sure you include this namespace in your SVG tag: xmlns:xlink="http://www.w3.org/1999/xlink" (you won’t need it if you decide to use href).

Part 2: Using CSS variables to apply different styles to your reused graphic

I chose a main color for the cube, which is a lighter and a darker shade for the sides and a stroke color. But what if we want to make a second cube a different color?

We can replace the fills and strokes with CSS variables to make these attributes more flexible. That way, we’ll be able to reuse the same cube unit with another palette (instead of defining a second unit with different colors for a second cube).

Why not add a class to the new cube and change the fill color with CSS? We’ll do that, but first, try to inspect a <use> element. You’ll notice it renders in the Shadow DOM. which means it is not vulnerable to scripts and styles, like elements in the normal DOM. Whatever values you define in the figure inside <defs> will be inherited by all its instances and you won’t be able to rewrite those with CSS. But if you replace those values with variables, then you’ll be able to control them in CSS.

In our cube unit, we’ll go through each side and replace the fill and stroke values with semantic variable names.

For example, this:

<rect fill="#00affa" stroke="#0079ad" />

…can be replaced with this:

<rect fill="var(--mainColor)" stroke="var(--strokeColor)" />

From here, we must duplicate the SVG to build a second cube. However, we don’t need to duplicate <defs> if we are keeping both in the same document. We can add a class to each SVG and control the color palette through CSS, redefining the values of the variable.

Let’s create a palette for the blue cube and another one for the pink cube:

.blue-cube { --mainColor: #009CDE; --strokeColor: #0079ad; --lightColor: #00affa; --darkColor: #008bc7;
} .pink-cube { --mainColor: #de0063; --strokeColor: #ad004e; --lightColor: #fa0070; --darkColor: #c7005a;
}
CodePen Embed Fallback

This way, we can add as many cubes as we want and change all colors from one place.

Part 3: Reusing animations

The idea for this instance is to break the cubes on hover — something like an exploded view so some pieces will move away from the center when we place the cursor over the cubes.

CodePen Embed Fallback

Let’s start by defining two movements, one for each axis: move Y and move X. By dividing the animations in movements, we’ll be able to reuse them in every cube. The animations will consist of moving the cube from its initial position to 30px or 50px away in one direction. We can use a transform translate (X or Y ) to achieve that. For example:

@keyframes moveX { to { transform: translateX(-35px); }
}

But if we want to be able to reuse this animation, it’s better to replace the numeric value with a variable, like this:

@keyframes moveX { to { transform: translateX(var(--translate, 35px)); }
}

If the variable is not defined, the default value will be 35px.

Now we need at least one class to bind to the animation. In this case, though, we need two classes to move cubes in the x-axis: .m-left and .m-right.

.m-left, .m-right { animation: 2s moveX alternate infinite; }

For the cube to move left, we need a negative value, but we can also declare a different number. We can define our variable like this inside the .m-left class:

.m-left { --translate: -50px; }

What’s happening here is we’re declaring that, when we add the class .m-left to one element, this will play the animation moveX (the one defined in the @keyframes) which will last two seconds to translate in the x-axis and reach a new position that is -50px left. Then, the animation alternates directions so that it moves from the last position and take two more seconds to go to its original state. And so on, because it’s an infinite loop.

We can declare another variable to the .m-right class but if we don’t, remember that it will take the 35px we declared at the beginning.

The default animation-play-state value is running but maybe we don’t want the cubes to move all the time. It would be very distracting and annoying to use on a site with some nearby content. So, let’s try to play the animation only on hover by adding this:

svg:hover .m-left { animation: 2s moveX alternate infinite;
}

You can try it by yourself and will find that the animation is jumping super fast to the initial state every time we place the cursor out of the cube. To avoid it, we can add the value paused at the end of the animation shorthand:

.m-left { animation: 2s moveX alternate infinite paused;
}

Now the animation is paused but will be running on hover by adding this line of CSS:

svg:hover * { animation-play-state: running; }

We can apply each class to different elements in the SVG. In the first blue cube, we are moving single cubes; in the second one, we’re applying those classes to groups of cubes.

One last thing…

It wasn’t until later that I realized I could reuse a single unit to build them all. I worked on the small cube to make it isometric enough so it could align easily with the other ones next to it. At this point, my unit was a <path>, but I decided to replace it with SVG shapes to reduce the code and get cleaner markup.

I learned that it is better to take some time to analyze what can be done with SVG before drawing every single shape and dealing with a huge amount of code. It might take more time at the beginning, but will save you a lot of time and effort in the long run.

The post Use and Reuse Everything in SVG… Even Animations! appeared first on CSS-Tricks.

14 WordPress Themes You Should Start Using in 2020

Even web designers who prefer to design websites from scratch eventually look for frameworks, past work, or shortcuts. That way they speed up their workflow.

And there are also those times when it’s hard to find the right template. You need help to create a special page and you feel compelled to build it from scratch.

It only makes sense to take full advantage of drag and drop, front-end editing, design modules, customizable demos, and other shortcuts. They will save you time. Also, they produce a quite similar quality and performance to the one you could achieve by building a website from scratch.

Another example of not wanting to start from scratch is when the website you want to build addresses a function or area that you’re not particularly familiar with. It could be a directory website, adding a knowledge base feature to an existing one, or even a performance feature like SEO.

If you can find a theme that promises to do the heavy lifting for you – grab it!

Just so you don’t get burned in the process, make sure the chosen theme is tops in its class – like the 14 presented here.

1. ListingPro

Perhaps building directory websites is your thing. But this is a design area in which most web designers aren’t all that familiar. And even if you’re quite good at it, ListingPro might just make your efforts that much more satisfying, and save you time while doing so.

And, if you’ve been relying on plugins to patch a design together, ListingPro is the only all-in-one WordPress directory solution on the market. It lets you get the job done without needing additional plugins, or any coding knowledge for that matter.

This #1 best-seller offers a comprehensive set of directory features and functions including –

  • Advanced Search
  • Ratings and Reviews
  • Front-end Listing Submission
  • Events and Ads Management
  • Pricing Plans including Stripe and PayPal
  • Built in Checkout that does not require WooCommerce
  • Listing Owner Dashboards
  • API support for autofill listing submissions

ListingPro is Elementor and WPBakery supported, and offers total design flexibility. It also provides 3 pre-built directory websites to kickstart a project.

Fantastic Theme and excellent customer service. Recently interacted with the support team member. All issues resolved quickly.Very fast turnaround.

– somymon80

Click here to learn even more about ListingPro.

2. BeTheme – Responsive Multi-Purpose WordPress Theme

One way to save design time is to have the necessary tools right at your fingertips. Another is a special feature that does much of the heavy lifting for you to get a website design project off the ground.

BeTheme does both; and it usually doesn’t matter what the purpose of your website is.

BeTheme, the biggest WordPress theme of them all is an ideal choice whether you’re planning your first website design project or you’re and advanced web designer.

As for the tools, BeTheme’s 40 core features supply everything you’ll need. They include:

  • Muffin Builder drag and drop page builder
  • Administration Panel for unlimited design options
  • Shortcode Generator and shortcodes
  • Layout Generator – create a page almost from scratch

As for the heavy lifting there’s the library of 500+ pre-built websites covering 30 industry sectors, all website types, and multiple business and personal niches.

These pre-built websites

  • are professionally crafted and attractive
  • are responsive and customizable
  • contain basic UX functionality

i.e., everything needed to get any project off to a lightning fast start

This Theme has great design quality and is very easy to get around. No technical skills needed in web development.

– syllabus

Click here; see if BeTheme is the time-saver you’re looking for.

3. Kalium

One way to build a website quickly and without unnecessary hassle is to import the content you need. Perhaps starting with a demo. Then, doing the necessary customizing and tweaking to get what you want.

Kalium provides a helpful selection of high-quality pre-made concept demos you can import. Plus you can import theme options, pages, sliders, widgets, or whatever else you need.

In addition to the pre-made concept demos the package includes

  • WPBakery, Revolution Slider, and Layer Slider
  • Product Filter Plugins
  • Shortcodes
  • A large and comprehensive font library
  • A powerful header builder
  • 30+ portfolio types and unique styles
  • Full eCommerce support
  • 16+ languages and RTL support

This top-selling theme offers free lifetime updates and excellent customer support. Plus it is fully responsive and GDPR compliant.

I’ve been using this theme for years now and it has been so flexible and adaptable as my business grows and my style evolves. There are lots of great themes like this that offer easy and quick customization but what I think really sets this one apart is the CUSTOMER SERVICE!!! The support team is beyond amazing – always answers questions promptly and are extremely helpful, saving me hours of time and headaches! Can’t say enough good things about this theme!

– itsmemissyxo

Click here to learn more.

4. TheGem – Creative Multi-Purpose High-Performance WordPress Theme

When you apply your creative talents to building a website from scratch it still takes time. When you have an assortment of tools to help, it takes less time. If you have the ultimate toolbox at your fingertips, i.e. TheGem, you might surprise yourself how easily your workflow speeds up. With the release of TheGem 4.0 it gets even better. 40,000 customers agree.

Awesome and fast Support! 🙂 Thank You!

– Nhecker

Click here to check out this awesome toolbox.

5. Total Theme

Plugins can boost you up or drag you down. It often depends on your site’s needs. Total will definitely boost you up and never drag you down. Total does not require a ton of 3rd party plugins to use all of the theme’s features, including:

  • Over 40 premade demos together with a one-click importer
  • More than 500 built-in styling options and 100+ drag and drop WPBakery modules

More than 41,000 happy customers will attest to this.

I work with TOTAL for years now and I’m still impressed by its support and documentation. If you have a theme to choose, TOTAL is the one (and only)! 😉

– spotmedias

Click here to learn more about Total.

6. Uncode – Creative Multiuse WordPress Theme

60,000+ sales to date make Uncode an Envato top seller. When this creative, pixel-perfect theme was designed, it was done so with an extraordinary amount of attention to detail.

Uncode is ideal for agencies, bloggers, and entrepreneurs. It is also ideal for building magazine and portfolio websites.

The best way to see what this WordPress theme could do for you is to visit the site and browse Uncode’s showcase of user-designed websites. You’ll be impressed.

Best Customer Support experience I have ever had. I had a hard time understanding the mobile and tablet customizations and have been helped out by their customer support team dozens of times. They are always friendly and helpful, and I love my site.

– oximedical

Browse the user-designed websites, and enjoy.

7. Schema

This fully responsive, ultra-fast theme has all the tools and elements to qualify as a “perfect” theme. Perfect or not, but certainly close to it, Schema has a feature that is lacking in most themes. This feature resolves a problem most web designers have and can save you a ton of time.

It’s the ability to make a website more SEO friendly than you might have thought possible.

Schema even guides the search engines through your site to show it off and get the best ratings.

Schema is one of the fastest themes around, I highly recommend it.

– Rashmi

Click here if SEO has become a constant challenge for you.

8. KnowAll

One way to make a good website a great one and drive up conversions is to replace a run-of-the-mill FAQ section with a knowledge base. It is a resource which most visitors will find extremely helpful.

With KnowAll, you can implement

  • Live search that provides instant answers and suggests related content
  • Feedback and action analytics that enable continuous improvement of the site

And you don’t have to do it from scratch.

Click here to learn more about this premium knowledge base solution.

9. Avada

When you invest in the #1 top selling theme of all time you can be pretty sure you’ve made a good decision. Avada’s collection of pre-built websites, demos, partial demos, and a huge array of supporting design elements ensures you have the material you need to build a top-quality website rather quickly.

  • Avada’s Fusion Builder is drag and drop.
  • The Dynamic Content System gives you unparalleled flexibility.
  • This premium theme integrates flawlessly with WooCommerce.

Everything works great with this theme!

– SiliconWaelder

Click here to learn more.

10. Neve

Neve is a multi-purpose theme that comes with ready-made designs for for startups, agencies, eCommerce shops, blogs and more. Other good reasons to check Neve out:

  • Neve loads crazy-fast and receives top scores on Page Speed Insights and GT Matrix performance tests
  • It is compatible with most popular page builders (Elementor, Brizy, Beaver Builder, Visual Composer, SiteOrigin, Divi), including Gutenberg
  • It comes with +50 ready-made starter sites
  • Neve is AMP optimized, responsive and 100% mobile ready

This theme is just great, totally customizable and perfectly integrated with Gutenberg.

aless81 (@aless81) on WordPress.org

Click here to discover even more about Neve.

11. Movedo

This premium quality theme by a top-rated author features a clean, modern design, amazing responsive options, great flexibility, and more than a few out-of-this-world automations and parallax effects.

They include mouse move, scrolling move, and column move. Movedo also features a Knowledge Base with a quick search option, plus it is designed for easy browsing.

To sum it up – Movedo rocks!

Great theme, overall astonishing functions and page builder, also the support is tremendous.

– cedzufrei

To see what dynamic parallax can do for your websites simply click here.

12. XStore | Responsive Multi-Purpose WooCommerce WordPress Theme

If you’re in an eCommerce frame of mind, don’t bother to look further for a solution. Describing XStore’s features can be short and sweet.

First, there is the single product page builder, a powerful header builder, and $300+ worth of premium plugins.

Second, there are 80 good-to-go shops.

Building your own eCommerce store could hardly be easier.

Fast response! Polite! Work hard! Thank you! You should definitely choose! This template is the best of many themes!!!

– KUNOICHIjp

Click here to see all the details.

13. Pofo – Creative Portfolio, Blog and eCommerce WordPress Theme

If you have building a portfolio website in mind, Pofo is the right choice. This modern and creative design theme is the ideal tool for creating business, agency, and personal portfolio websites.

This is especially true if you wish to incorporate blogging and eCommerce into your sites.

Pofo is fast, flexible, and customizable with 200+ demo pages, 25+ homepages, and 150 pre-built elements to work with.

While everything is great about this theme, from Design Quality to Flexibility. The main reason why I’m using this theme for 5 websites, is the Customer Support. This is absolutely perfect. Within time, friendly, professional. Sending CSS codes. I love working with this Pofo theme.

– studiojas

Click here to learn more.

14. Hongo – Modern & Multipurpose WooCommerce WordPress Theme

This modern, multi-purpose theme was specially created with WooCommerce stores, blogs, and company websites in mind. Hongo’s package includes WPBakery, Revolution Slider, and an impressive collection of out of the box premium features. The collection includes comparing products, quick view, product videos, and 11 ready store demos.

Hongo also provides users with quality online documentation. Its customer support enjoys high ratings.

Simply the great designs and best theme for WooCommerce, loading fast, customizable and easy to use with the detailed documentation. Their support team is technically sound and very kind to guide wherever needed. We have bought some other themes from ThemeZaa now and they have never let us down, thanks!

– diyaatps

Click here to learn more about this new and modern theme.

*****

Now that you’ve seen 14 possible ways to make your website building adventures easier, we hope you’ve been able to drill down to one or more that makes perfect sense to you.

We would appreciate it if you would share this article with a friend or with your social media group.

 

[– This is a sponsored post on behalf of BawMedia –]

Source
p img {display:inline-block; margin-right:10px;}
.alignleft {float:left;}
p.showcase {clear:both;}
body#browserfriendly p, body#podcast p, div#emailbody p{margin:0;}

Privacy Settings
We use cookies to enhance your experience while using our website. If you are using our Services via a browser you can restrict, block or remove cookies through your web browser settings. We also use content and scripts from third parties that may use tracking technologies. You can selectively provide your consent below to allow such third party embeds. For complete information about the cookies we use, data we collect and how we process them, please check our Privacy Policy
Youtube
Consent to display content from Youtube
Vimeo
Consent to display content from Vimeo
Google Maps
Consent to display content from Google