100 Jamstack Tools, APIs & Services to Power Your Sites

Original Source: https://www.sitepoint.com/jamstack-tools-services-apis/?utm_source=rss

We’ve explained the Jamstack, a popular new way to build secure, scalable, high-performance sites. Now we’ll introduce you to the tools, services, and APIs that power Jamstack sites.

The A in Jamstack stands for API. APIs can do anything for you, from sending a form to authenticating a user, or from storing and retrieving data in real time to shopping for products.

In this article, we’ll do an extensive review of existing APIs and how they compare to one another. This review couldn’t possibly encompass the whole spectrum of third-party APIs that you can integrate into your website, but hopefully you’ll still find the coverage enlightening enough.

We’ll use the words “headless”, “detached”, and “serverless” a lot in this article. If you haven’t already, check out our introduction to the Jamstack, which covers all the basics.

Hosting (Mostly for Free)

Provided: Netlify

Hosting a Jamstack site usually involves automated deployment pipelines. For example, you might have a repository in GitHub which, on every push, automatically triggers an online deployment (via webhooks), running the necessary build tools (such as Jekyll) and regression tests (via Travis CI).

Sound difficult? It can be a surprisingly simple process!

Most of the services here include these goodies out of the box:

SSD drives
CDN deployments
free SSL (including for custom domains)
command line deployments and rollbacks

Note: look out for another article in this series, coming soon, covering how to use these services.

Services
Google Firebase and AWS Amplify

<!– ![The Firebase logo](firebase-logo.png)

Image source –>

Firebase Hosting is Google’s take on a hosting service that’s easy to understand and implement, and it’s free to use (limits apply). Firebase’s backbone actually lies on top of the Google Cloud Platform (GCP), and you can in fact access and tweak some Firebase deployments through the GCP console. But by implementing something of an “gateway” (Firebase) that transparently handles GCP resources for us, Google gave developers a brand new and highly improved user experience (UX) … and the Firebase’s YouTube channel is just brilliant! 👏

AWS Amplify is also an effort to reduce the complexities of Amazon Web Services (AWS) for web and mobile deployment that doesn’t quite offer free hosting but 12 months of free use for new accounts for its Storage with Amplify as part of the AWS Free Tier.

Google really made a brilliant move with the Firebase family of products by “detaching” them from the GCP, but Amazon went half-way with AWS Amplify. It sure is a dramatic improvement from the regular AWS workflow, especially for novice users, and its documentation hub is superb and way more down-to-earth than the way Amazon usually documents services. But Amplify is still accessed from the same old (horrifically bloated) console. You still need a credit card to just open an account, deployments are still region-specific (no built-in CDN, seriously?), and the workflow isn’t as straightforward when compared to that of Firebase or Netlify.

GitHub Pages and GitLab Pages

Both hosting services for Git repositories also have a built-in service to host static pages right out of your codebases, 100% free: GitHub Pages and GitLab Pages.

In a future article we’ll cover how to use these services, but in the meantime make sure to check out these easy-to-follow guides:

Getting Started with GitHub Pages
Hosting on GitLab.com with GitLab Pages

Netlify and Heroku

In a very short period of time, Netlify not only coined the Jamstack term but also positioned itself as the place to go for all things static. While you could certainly accomplish more with an elaborated AWS pipeline, the simplicity and unparalleled ease of use that Netlify offers is unbeatable. Want to host a static site? Just drop it here and it’s online. Want automatic updates? Link a repo and just push a commit. And batteries are included — instant builds, worldwide CDN, free SSL, CLI tool, on-click rollbacks, and more.

Heroku is the only service in this list that allows you to host dynamic pages: Node.js, Ruby, Python, Java, PHP, Go, Scala and Clojure (check their Language Support page). So if you aren’t yet quite ready to go static, this might be a good way to test your dynamic sites online for free.

Other Services

With 194 data centers as of 2020, Cloudflare is — by many metrics — the company that offers the lowest latency for their DNS and CDN services around the world. They serve big companies but also have a number of services oriented to developers, like Workers Sites. The service isn’t free ($5/mo minimum charge) but it’s as top performant as you can get, and fairly easy to use.

Other tools targeted at static pages include Aerobatic, which offers a free trial with no credit card required and support for internationalization (i18n) and full-text search built-in plugins; Surge.sh with npm run scripts and CI services; and Vercel (formerly ZEIT Now) with an Edge Network serving big names such as Twilio and The Washington Post.

Comparison

Service
Free plan
Easy-of-use
Tooling

Aerobatic
1 month
easy
good

Firebase Hosting
yes
easy
very good

GitHub Pages
completely free
easy
poor

GitLab Pages
completely free
easy
good

Heroku
yes
somewhat easy
very good

Netlify
yes
extremely easy
very good

Storage with Amplify
1-year (new accounts)
somewhat easy
very good

Surge.sh
yes
easy
good

Vercel
yes
easy
good

Workers Sites
no
somewhat easy
good

Storing and Retrieving Data: Real-time NoSQL Databases

NoSQL solutions like MongoDB have been coexisting with relational databases like MySQL for some time (see the differences and how to choose), but real-time processing takes NoSQL to the next level by enabling cloud storage for state management, such as a user entering their name or clicking a radio button.

If you’re familiar with Redux and Vuex — React and Vue.js libraries for state management, respectively — think of integrating that concept with a cloud storage provider.

Services

Amazon DynamoDB is a “fully managed, multiregion, multimaster, durable database with built-in security, backup and restore, and in-memory caching for internet-scale applications”. But as with many things AWS, it’s difficult to implement and very hard to debug (see Why Amazon DynamoDB isn’t for everyone, by Forrest Brazeal). In all fairness to Amazon, they also built DataStore into AWS Amplify (with GraphQL and REST API support) with a more straightforward approach, in line with the simplicity of the rest of Amplify’s products.

Google Firestore made real-time NoSQL databases — a fairly complex topic in and of itself — as simple as they can be, with pretty much all the capabilities DynamoDB has. It’s very well documented (with introductory clips that are fun to watch). And React and Vue.js have wrappers around Firestore with react-redux-firebase and Vuexfire, respectively.

Cloudflare sure knows how to take performance to the very extreme, and Workers KV, a serverless key-value storage for applications, is a fine example of what a well engineered product looks like. The premise of Workers KV is that you can access a key as if it were a local file within your app, and the content will be the value stored for that key. That’s it — no API to implement, no extra coding. And because of the unbeatable performance of the Cloudflare CDN, this approach can actually be faster than querying a NoSQL database. And as simple as it is, it scales seamlessly to millions of requests. 👏

And finally, there’s FaunaDB, a startup that crafted a solution with native GraphQL and a simple pricing (including a free plan) that can be implemented in minutes.

Managing Content: Headless CMS

In the “monolithic” way of doing things, whenever we used a given content management system — such as WordPress, Django, or Joomla! — it meant that we also needed to use the front-end engine that came attached to it, as back and front end were “coupled” components of a single piece of software (see our introduction to the Jamstack for more info about tightly vs loosely coupled sites).

Enter the headless CMS — a back end only without a front end. Since a headless CMS would normally expose an API or generate static content in the way of Markdown or HTML files, the front end can be anywhere really. In fact, multiple and simultaneous interfaces can be created for web sites, mobile apps, and Internet of Things (IoT) apps.

trends.embed.renderExploreWidget(“TIMESERIES”, {“comparisonItem”:[{“keyword”:”headless cms”,”geo”:””,”time”:”today 5-y”}],”category”:0,”property”:””}, {“exploreQuery”:”date=today%205-y&q=headless%20cms”,”guestPath”:”https://trends.google.com:443/trends/embed/”});

Products and Services

There are a number of headless CMSs, both as software you can download and configure where you do the deployments yourself, or offered in the software-as-a-service (SaaS) model where everything is taken care of for you.

Some features you can expect to find:

localization (l10n) and internationalization (i18n)
microservices architecture with a RESTful API
editor interface
customization
versioning*

* Since some headless CMS will integrate smoothly with your git repo, the versioning capability can actually be a remarkable improvement over a regular CMS.

Self-hosted Headless CMS

Ghost, “the #1 open source headless Node.js CMS”, is certainly the one with the most stars on GitHub. Not only can Ghost handle content, but it also offers a number of integrations to manage payments (Stripe), email lists (MailChimp), shopping (Shopify), and many more. And then there’s Ghost(Pro), which is the official managed hosting for Ghost with commercial support.

Fairly close to Ghost in popularity comes Strapi, with REST and GraphQL APIs, and 1-click deployments on Heroku, AWS, and DigitalOcean. It has “starters” (template projects) to work seamlessly with Gatsby, Vue.js with Nuxt.js, React with Next.js, and Angular. It also runs on Node.js and has support for a number of database engines.

Netlify CMS is also a popular option built as a single–page React app. There’s Directus, which wraps custom SQL databases with an API and provides an intuitive admin app to manage its content, and the commercial companion Directus Cloud. There’s also TinaCMS, which is also React-based, and Ponzu, Copckpit, and many more, which you can explore oin the comprehensive list provided by headlesscms.org.

SaaS Headless CMS

CloudCannon is the cloud CMS for Jekyll (we’ll review Jekyll later in the “static site generators” section), with smooth integration with GitHub, Bitbucket and Dropbox. They have a free plan as well but with no global CDN hosting.

Contentful is something different: a content hub where business owners, marketers, developers and project managers can all go to set and manage all of the data sources of an organization. And their headless CMS is just a part of that strategy. The Contentful platform is fully featured, very well documented, with plenty of open-source tools. And while the pricing is a bit confusing, there’s actually a free plan that only requires attribution.

There are other SaaS headless CMSs with free plans, such as DatoCMS and Sanity with a proposition similar to that of Contentful; Forestry, with support for a number of static generators; GraphCMS, with GraphQL support; and Prismic. These are just a few of the many options.

Sending Information: Forms without Code

Sending data through forms has forever been one of the main uses for server-side processing. There are essentially two approaches to addressing this problem on a static site, each with pros and cons.

From Builders, Embedded and Hosted Forms

Many times integrating a “powered by” external form is more than enough to collect email addresses or to receive feedback.

Google Forms have offered this possibility since 2008 entirely for free, with a simple interface that stores submissions on Google Sheets, and that can send alerts via email every time there’s a submission.

Formstack takes forms to another level by providing an integrated workflow supporting digital signatures, document generation, Salesforce integration, and more. They offer a free tryout but no free plans.

Then you have the extremely easy-to-use form builders JotForm and Wufoo, which integrate handling payments, among other things, or Typeform, which makes forms and surveys … pretty? All of them offer free plans.

External API: Form Processing as a Service (FPaaS)

Sometimes a builder won’t cut it, as you need more flexibility to present information and fields, or to fully integrate the look and feel of the form with the rest of your website. For this you will need to integrate an API.

The way these services work is surprisingly easy: you specify a URL for submission that will do the processing for you. At most you’ll have to set a few things up but most probably won’t need to do any extra coding.

There are a number of providers offering free plans, such as Form.IO, Formcarry, Formspark, and Netlify Forms. They all work in a similar way and are very easy to implement.

FormDen and FormKeep are also form builders that can otherwise be used just as back ends, though none of them offer free plans.

Programming Server-Side Logic: Function as a Service (FaaS)

Couldn’t find an API that does quite what you want? Create it! You don’t need to resort back to a hosted back-end system to process server-side logic, with all the hassle that comes with it (maintenance, bills, credentials, security patches). Instead, you can implement a micro-service in your language of choice (oftentimes JavaScript, Python, or Go), encapsulate that logic into functions, and offer them through a RESTful API.

As with pretty much everything else in this list, you won’t be paying anything for a function that’s not being actively used, so no worries for just leaving it sitting there (but beware that spikes in traffic might also trigger extra billing).

Providers

While the implementation details for AWS Lambda, Azure Functions and Google Cloud Functions may differ, they all work in pretty much the same fashion and you’ll need a degree of familiarity with AWS, Azure or GCP. AWS Lambda has the richest language support of them all (and also Amazon API Gateway to help you wrap your functions into a maintainable API with monitoring tools), while Azure — not surprisingly — has the best support for .NET Framework and .NET Core (with different versions supporting different runtimes and even TypeScript transpiled to JavaScript). But be aware that Azure systematically ranks as the slowest service by a margin.

Cloud Functions for Firebase and Netlify Functions are wrappers around Google Cloud Functions and AWS Lambda, respectively. They greatly simplify the management of functions on the cloud, as you effectively can get away without even having an account on such services. Code deployment and versioning become trivial with Netlify — which also has very good community support — as it will smoothly integrate with your repo offering stage, previewing, and rolling back at a click (or a commit). Simplicity naturally comes at the expense of losing some flexibility (see Firebase Cloud Functions: the great, the meh, and the ugly by Pier Bover).

IBM Cloud Functions (based on Apache OpenWhisk) and Cloudflare Workers are other services you might want to look at. IBM has an impressive list of supported languages, including the option to deploy Docker containers with your own runtime. However, it ranked somewhat poorly performance wise. And just as Netlify systematically manages to make things the simplest, Cloudflare again makes things the fastest (and by a difference).

Comparison

service
languages
overhead*
coldstart*
difficulty
support

AWS Lambda
C#, Go, Java, JavaScript, PowerShell, Python, Ruby
86 ms 🟢
589 ms
high
👍 very good

Azure Functions
C#, F#, Java, JavaScript and TypeScript, PowerShell, Python
760 ms 🔴
5,907 ms 🔴
high
👎 very poor

Cloud Functions for Firebase
JavaScript and TypeScript
642 ms 🔴
168 ms
low
👍 very good

Cloudflare Workers
JavaScript, COBOL
70 ms 🟢
76 ms 🟢
intermediate
intermediate

Google Cloud Functions
Go, Java, Node.js, Python
642 ms 🔴
168 ms
high
👍 very good

IBM Cloud Functions
.C#, Go, Java, JavaScript, PHP, Python, Ruby, Swift, and Docker containers
136 ms
2,103 ms 🔴
high
no info

Netlify Functions
Go, Node.js
86 ms 🟢
589 ms
very low
👍 very good

* As measured by λ Serverless Benchmark, the overhead is the time from request to response without the time the function took (for a concurrency of 50), and the coldstart is how long the servers takes to respond when queried are spanned every 3 hours; the lower the values, the better.

Authenticating Users: Identity as a Service

Identity as a Service (IDaaS), also called sometimes Authentication as a Service (AaaS), involves managing a full user registration, confirmation, and authentication with just APIs. The Geist of “stateless authentication” is that a user will authenticate against a third-party and come back to you with a valid “token” that you can verify, or revoke if need be.

In some cases, a provider might even offer a “drop-in” user interface (UI) that will work seamlessly across desktop and mobile, all of which could potentially save you very long hours of work.

Services

Auth0 has been in business the longest and has quickstart guides for a number of scenarios. It’s an excellent provider if you want to implement a complex solution and already have some experience implementing authentication. But as they point out, “identity is complex, deal with it”. The large scope Auth0 services (universal login, single sign on (SSO), multifactor authentication, branch password detection, and so on) can be overwhelming if you’re just starting on the topic.

Firebase Authentication (with its ready-to-use UI) and Authentication with Amplify are also very comprehensive and flexible, and somewhat presented in a more straightforward manner than Auth0. Firebase also offers anonymous authentication! Curious? Check out this clip:

Once again, Netlify seems to come up with the easiest solution to implement with Netlify Identity and its open-source zero config netlify-identity-widget to create a secure login in 10 minutes! But of course, there are some limitations (check out Four Dealbreakers in Netlify Identity, by Jean Cochrane).

You can also check Okta, FusionAuth and LoginRadius, all of which have free plans. There are no freebies for Ping Identity, OneLogin, and Ubisecure, which are more oriented to the enterprise sector. Finally, consider Cloudflare Access, as everything Cloudflare does is rock solid.

Going F·A·S·T: Static Site Generators (SSG)

I can hear some of you saying “all of this might be okay for future projects, but my sites are already dynamic, so what to do?” Here’s when static site generators enter the picture.

You can have the best of both worlds — the convenience of a familiar CMS and static pages with code and data splitting, preloading, caching, image optimization, and all sorts of performance enhancements. An SSR will bridge that gap by querying your database and generating static output out of it (for example, Markdown pages), and with some settings to set your template, you’ll be all set.

The listing here is tiny compared to the ever increasing list of SSRs. Have a look at StaticGen for more info.

Main Products

GatsbyJS is powered by React.js and webpack, meaning that it can generate progressive web apps (aka PWAs, websites that look and feel like an apps). It also supports GraphQL (see Write Apps with Better Building Blocks) and it has +1,000 plugins to get data from anywhere (WordPress, Drupal, Contentful, GraphCMS, DatoCMS, and many more). See how GatsbyJS says it compares to its main competitors, Hugo and Jekyll.

All of this flexibility comes at a cost, as setting and customizing GatsbyJS can be a time-consuming process, and if you don’t have a decent understanding of React — and therefore JavaScript — you won’t be able to make much of it. That’s where Gatsby Cloud comes in, offering support to build and maintain Gatsby sites for free or for a fee, where you could automate your fast builds, access to previews, generate daily edits, and fire deployments with ease to Netlify, Cloudflare, AWS CloudFront or Akamai.

Hugo claims to be “the world’s fastest framework for building websites”, and it sure can generate massive sites in milliseconds. With built-in templates (literally hundreds of them available) and native support for internationalization (i18n), it’s also one of the most popular SSGs. Hugo is a Go app, and while Go isn’t hard to set and learn, you’ll definitely need to be checking the documentation often if you aren’t familiar with it.

Unlike GatsbyJS, configuring and deploying Jekyll is a rather straightforward process. Furthermore, Jekyll is the only SSR supported by GitHub Pages (Tom Preston-Werner, creator of Jekyll, is also a co-founder of GitHub), and can smoothly deploy static sites for free right out of your GitHub repos! Jekyll uses Shopify’s Liquid template language, which is also easy to learn. The downsides? As a Ruby app, Jekyll can be hard to set on a Windows environment, and optimizations such as minimizing JavaScript code and image preloading aren’t included by default. In fact, Jekyll doesn’t even aim at generating a PWA but just purely static sites — which might still be fine depending on what you need.

Comparison

Product
Language
Templating
Setting
GitHub stars

GatsbyJS
JavaScript
React.js
difficult

Hugo
Go
Go (library)
intermediate

Jekyll
Ruby
Liquid
easy

Others

WP2Static is an SSR designed specifically for WordPress (WP). It has a small but very interesting set of plugins, like Algolia search, and Cloudflare Workers and Netlify deployments. HardyPress is actually a SaaS solution to generate static WP sites, and for a fee you’ll have an admin panel from where you can enter some credentials to access your online WP installations to manage everything: shut down live WP installs that were already imported, transparent deployment to global a CDN, HTTPS, forms, search. Other WP-related SSGs with commercial support are Shifter, Strattic, and Sitesauce.

Since I am admittedly biased towards Vue.js, I had to include VuePress, which is intended to generate single page applications (SPAs) and has a minimal setup with markdown-centered files, and it’s also powered by webpack. Gridsome and Nuxt.js are more featured Vue.js powered frameworks with SSR capabilities.

Selling and Processing Payments: Headless Shopping Carts

The architecture and benefits of headless ecommerce is not that different from that of a headless CMS: massive cost reduction (hosting, licenses, maintenance), less time to market, seamless integration, and — a big one for commerce — “omnichannel” capabilities.

Continue reading
100 Jamstack Tools, APIs & Services to Power Your Sites
on SitePoint.

Create A Responsive Dashboard With Angular Material And ng2-Charts

Original Source: https://www.smashingmagazine.com/2020/07/responsive-dashboard-angular-material-ng2-charts-schematics/

Create A Responsive Dashboard With Angular Material And ng2-Charts

Create A Responsive Dashboard With Angular Material And ng2-Charts

Zara Cooper

2020-07-27T10:00:00+00:00
2020-07-27T17:34:36+00:00

Creating a dashboard from scratch is often pretty complicated. You have to create tools to collect data on items of interest. Once collected this data has to be presented in an easy to understand and meaningful way to your users. It involves intricate planning of what data to include and how to display it effectively. Once you have a plan, implementing the design is a massive task especially since it involves building multiple components.

With Angular Material and ng2-charts, you can take advantage of schematics to cut down the effort and time you may spend building a dashboard. Angular Material ships with a number of schematics that you could use to generate a dashboard. Similarly, ng2-charts provides schematics for generating multiple chart components. In this article, I’ll illustrate how to use both ng2-charts and Angular Material to set up a dashboard fairly quickly.

An Example

To illustrate how to build a dashboard, we’ll take the example of an online store selling leather goods like bags, wallets, key holders, and so on. The store owner would like to track information such as where customers come from to their online store, how their products sell, how traffic sources relate to sales, among other things.

We’ll build a dashboard to display this information and help the store owner analyze it. The dashboard will contain four small summary cards, four different kinds of charts, and a table listing most recent orders made. The four summary cards will display information such as total revenue from sales, average order value, the total number of orders, and number of returning customers. The charts will display the number of units sold for each product, sales by traffic source, online store sessions over time, and sales for the week.

Prerequisites

To follow along, you’ll need to have Angular CLI installed. If you do not have it installed, you can find out how to get it at cli.angular.io. If you’re not starting from a pre-existing Angular project, you need to generate one by running ng new <your project name>. For instance, to create an admin panel for the aforementioned store, we’ll run:

ng new store-admin-panel

Your project also needs to have routes configured for it. If you’re starting from a new app, select yes when prompted on whether to add an Angular Routing module during your project setup above.

Add Angular Material And Ng2-Charts To Your Project

Angular Material ships with various schematics for generating a variety of useful components like address books, trees, tables, navigation, and so on. To add Angular Material to your project, run:

ng add @angular/material

Pick a theme from the options provided in subsequent prompts. Next, you’ll be prompted to choose whether to add Angular Material typography styles and browser animations. You do not need these and could just respond no.

Next, you’ll need to install ng2-charts. ng2-charts requires charts.js as a dependency. To install ng2-charts run:

npm install ng2-charts –save

Then install charts.js:

npm install chart.js –save

To access the charts, add the ChartsModule to the AppModule’s imports.

import { ChartsModule } from ‘ng2-charts’;

@NgModule({
imports: [

ChartsModule,

]
})

Lastly, install ng2-charts schematics as a dev dependency because they do not ship with ng2-charts by default.

npm install –save-dev ng2-charts-schematics

Generating A Navigation Component

First off, we’ll need to add a navigation component to help users maneuver through the app comfortably. The navigation should contain links to the dashboard and other pages that will be part of the admin panel. Angular material provides a schematic that generates a navigation component. We’ll name this component nav. Adding a side nav to the application is accomplished by running:

ng generate @angular/material:navigation nav

To link other routes in the navigation, use the routerLink directive and change the page name in the toolbar depending on what route a user is on.

// nav.component.ts

menuItems = [‘dashboard’, ’sales’, ‘orders’, ‘customers’, ‘products’];

<!–nav.component.html–>

<mat-nav-list>
<a *ngFor=”let item of menuItems” mat-list-item [routerLink]=”‘/’+item”> {{item | titlecase}} </a>

To see this component, add it to app.component.html.

<!–app.component.html–>
<app-nav></app-nav>

This is what the NavComponent looks like.

Navigation component

Navigation component (Large preview)

Since the nav will be displayed alongside other components, adding a router-outlet to it would help switch between the other different components. In the nav.component.html template, just after the closing </mat-toolbar>, replace the <!– Add Content Here –> comment with <router-outlet></router-outlet>.

<!–nav.component.html–>
<mat-sidenav-container>

<mat-sidenav-content>
<mat-toolbar>

</mat-toolbar>
<router-outlet></router-outlet>
</mat-sidenav-content>
</mat-sidenav-container>

In the screenshots that follow in this article, this nav component will be omitted to better highlight the dashboard we’ll be generating for the sake of the tutorial. If you’re following along while building this dashboard, the nav will still appear as pictured above in your browser with the dashboard within it.

Generate The Dashboard

The most important part of the dashboard is its layout. It needs to hold all the components mentioned earlier and be responsive when displayed on different devices. To generate the dashboard layout, you’ll need to run the @angular/material:dashboard schematic. It will generate a responsive dashboard component. Pass the preferred name for your dashboard to the schematic. In this instance, let’s name it dash.

ng generate @angular/material:dashboard dash

To view the newly generated dashboard within the nav component, add a route for it to the router.

// app-routing.module.ts
import { DashComponent } from ‘./dash/dash.component’;

const routes: Routes = [{ path: ‘dashboard’, component: DashComponent }];

@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})

Once done, to see the results, run npm start and head on over to localhost:4200/dashboard. You should see this:

generated dashboard component

Generated dashboard component (Large preview)

The schematic generates four cards in the template and displays them in a responsive grid. The Angular Material CDK uses the Layout package to style this responsive card grid. The BreakpointObserver utility of the Layout package assesses media queries and makes UI changes based on them. There are various breakpoints available but within the generated component, only two categories are catered for. The Breakpoints.Handset and other queries that do not match it. The Layout package specifies 14 breakpoint states that you can use to customize the responsiveness of your dashboard.

// dashboard.component.js

cards = this.breakpointObserver.observe(Breakpoints.Handset).pipe(
map(({ matches }) => {
if (matches) {

}

})
);

Going back to the dashboard, since four summary cards, four charts, and a table will be on the dashboard, we need nine cards in total. Breakpoints.Handset and Breakpoints.Tablet matches will display in a one-column grid where:

The four summary cards will span one row.
The charts will span two rows.
The table will span four rows.

Non-Breakpoints.Handset and non-Breakpoints.Tablet matches will display in four columns where:

The four summary cards will span one row and one column.
The charts will span two rows and two columns.
The table will span four rows and four columns.

It should look something like the screenshot below in non-Breakpoints.Handset and non-Breakpoints.Tablet matches. On Breakpoints.Handset and Breakpoints.Tablet matches, everything will just display in one column.

dashboard component with additional cards

Dashboard component with additional cards (Large preview)

Create A Card Component

In the dashboard component, all the cards are generated through iteration. To prevent repetition, when adding all the new components, we’ll create a reusable card component. The card component will accept a title as input and use ng-content to dynamically add the rest of the content. To create the card component, run:

ng g c card -m app –style css

From the dashboard component template, we’ll just take the markup enclosed within the <mat-card> tag and place it In the card template:

<!–card.component.html–>
<mat-card class=”dashboard-card”>
<mat-card-header>
<mat-card-title>
{{title}}
<button mat-icon-button class=”more-button” [matMenuTriggerFor]=”menu” aria-label=”Toggle menu”>
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menu=”matMenu” xPosition=”before”>
<button mat-menu-item>Expand</button>
<button mat-menu-item>Remove</button>
</mat-menu>
</mat-card-title>
</mat-card-header>
<mat-card-content class=”dashboard-card-content”>
<ng-content></ng-content>
</mat-card-content>
</mat-card>

To add the title as input to the card:

// card.component.ts
import { Component, Input } from ‘@angular/core’;

export class CardComponent{
@Input() title: string;


}

To style the card:

/*card.component.css*/
.more-button {
position: absolute;
top: 5px;
right: 10px;
}

.dashboard-card {
position: absolute;
top: 15px;
left: 15px;
right: 15px;
bottom: 15px;
}

.dashboard-card-content {
text-align: center;
flex-grow: 1;
display: flex;
flex-direction: column;
align-items: center;
max-height: 100%;
justify-content: center;
align-items: stretch;
}

mat-card {
display: flex;
flex-direction: column;
}

Adding Cards To The Dashboard

Since the dashboard elements will be added individually and not through iteration, the dashboard component needs to be modified to account for this. In dashboard.component.ts, remove the cards property and replace it with a cardLayout property instead. The cardLayout variable will define the number of columns for the material grid list and how many rows and columns each of the dashboard cards will span. Breakpoints.Handset and Breakpoints.Tablet query matches will display in 1 column and those that do not match will display in 4 columns.

// dashboard.component.js

cardLayout = this.breakpointObserver.observe(Breakpoints.Handset).pipe(
map(({ matches }) => {
if (matches) {
return {
columns: 1,
miniCard: { cols: 1, rows: 1 },
chart: { cols: 1, rows: 2 },
table: { cols: 1, rows: 4 },
};
}

return {
columns: 4,
miniCard: { cols: 1, rows: 1 },
chart: { cols: 2, rows: 2 },
table: { cols: 4, rows: 4 },
};
})
);

In the dash.component.html template, replace the colspan and rowspan values of mat-grid-tile elements and the cols property of the mat-grid-list element.

<!–dash.component.html–>
<div class=”grid-container”>
<h1 class=”mat-h1″>Dashboard</h1>
<mat-grid-list cols=”{{ ( cardLayout | async )?.columns }}” rowHeight=”200px”>
<!–Mini Cards–>
<mat-grid-tile *ngFor=”let i of [1, 2, 3, 4]” [colspan]=”( cardLayout | async )?.miniCard.cols”
[rowspan]=”( cardLayout | async )?.miniCard.rows”>
<app-card title=”Card {{i}}”><div>Mini Card Content Here</div></app-card>
</mat-grid-tile>
<!–Charts–>
<mat-grid-tile *ngFor=”let i of [5, 6, 7, 8]” [colspan]=”( cardLayout | async )?.chart.cols”
[rowspan]=”( cardLayout | async )?.chart.rows”>
<app-card title=”Card {{i}}”><div>Chart Content Here</div></app-card>
</mat-grid-tile>
<!–Table–>
<mat-grid-tile [colspan]=”( cardLayout | async )?.table.cols” [rowspan]=”( cardLayout | async )?.table.rows”>
<app-card title=”Card 9″><div>Table Content Here</div></app-card>
</mat-grid-tile>
</mat-grid-list>
</div>

The dashboard will end up looking exactly like the most recent screenshot linked above.

Generating The Charts

The four charts that we need for the dashboard are:

A radar chart of products by unit sold.
A pie chart of sales by traffic source.
A bar chart of online store sessions.
A line chart of sales across the year.

Similar to creating the dashboard, generating chart components involves running a schematic. Using the ng2-charts schematics, generate the four different charts. We’ll place them in a folder called charts. Run ng generate ng2-charts-schematics:<chart type> <chart name>.

ng generate ng2-charts-schematics:radar charts/product-sales-chart
ng generate ng2-charts-schematics:pie charts/sales-traffic-chart
ng generate ng2-charts-schematics:line charts/annual-sales-chart
ng generate ng2-charts-schematics:bar charts/store-sessions-chart

After running these commands, all four chart components are generated and are populated with sample data ready for display. Depending on what data you’d like to show, pick charts that most suit your data visualization needs. For each of the charts generated above, add the chartContainer class to the divs that enclose the canvas element in the chart templates.

<div class=”chartContainer”>
<canvas baseChart width=”400″ height=”400″>

Next, add this styling to styles.css so that they could be accessible to all the chart components.

/*styles.css*/

.chartContainer canvas {
max-height: 250px;
width: auto;
}

.chartContainer{
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}

Adding Data To The Charts

The generated chart components come with sample data already plugged in. If you have pre-existing services that provide your own data, you can add this data from them to the chart components. The charts take labels for the x-axis, data or data sets, a chart type, colors, a legend as well as other customization options. To provide the data and labels to the charts, create a service that will fetch data from a source of your choice and return it in a form that the charts accept. For instance, the AnnualSalesChartComponent receives its dataset and labels from the SalesService’s getSalesByMonth method which returns an array of sales for each month for the current year. You can find this service here and data it returns here. Inject the service as a private property to the AnnualSalesChartComponent constructor. Call the method that returns the required chart data from the service within the ngOnInit lifecycle hook.

// annual-sales-chart.component.ts
import { SalesService } from ’src/app/sales/sales.service’;

export class AnnualSalesChartComponent implements OnInit {
public salesChartData: ChartDataSets[] = [
{ data: [], label: ‘Total Sales’ },
];

public salesChartLabels: Label[] = [];

constructor(private salesService: SalesService) { }
ngOnInit() {
this.salesService.getSalesByMonth().subscribe({
next: salesItems => {
salesItems.forEach(li => {
this.salesChartData[0].data.push(li.revenue);
this.salesChartLabels.push(li.month);
});
},

});
}
}

Adding Charts To The Dashboard

The next step involves adding the charts to the dashboard, in dash.component.html. Here’s what that looks like:

<!–dash.component.html–>

<!–Charts–>
<mat-grid-tile [colspan]=”( cardLayout | async )?.chart.cols” [rowspan]=”( cardLayout | async )?.chart.rows”>
<app-card title=”Monthly Revenue”>
<app-annual-sale-chart></app-annual-sale-chart>
</app-card>
</mat-grid-tile>
<mat-grid-tile [colspan]=”( cardLayout | async )?.chart.cols” [rowspan]=”( cardLayout | async )?.chart.rows”>
<app-card title=”Product Sales”>
<app-product-sales-chart></app-product-sales-chart>
</app-card>
</mat-grid-tile>
<mat-grid-tile [colspan]=”( cardLayout | async )?.chart.cols” [rowspan]=”( cardLayout | async )?.chart.rows”>
<app-card title=”Sales by Traffic Source”>
<app-sales-traffic-chart></app-sales-traffic-chart>
</app-card>
</mat-grid-tile>
<mat-grid-tile [colspan]=”( cardLayout | async )?.chart.cols” [rowspan]=”( cardLayout | async )?.chart.rows”>
<app-card title=”Online Store Sessions by Traffic Source”>
<app-store-sessions-chart></app-store-sessions-chart>
</app-card>
</mat-grid-tile>

This is what the resultant responsive dashboard looks like.

dashboard with charts

Dashboard with charts (Large preview)

Generating A Table

We’ll add an orders table to give the shop owner an overview of the most recent orders placed and their status. To generate the orders table component, run the schematic:

ng generate @angular/material:table orders-table

This will generate a table component that will look like this.

table generated by Angular Material schematic

Table generated by Angular Material schematic (Large preview)

Tables with many columns may be difficult to make responsive for handset and tablet views. When adding the table to a card, make it horizontally scrollable so that all the data can be viewed properly and is not obstructed. You can do this by adding the styling below to your table component:

<!–table.component.html–>
<div class=”mat-elevation-z8 small-table”>
<table mat-table class=”full-width-table” matSort aria-label=”Elements”>

/*table.component.css*/

.small-table{
overflow-x: scroll !important;
}

To add the table to the dash component:

<!– dashboard.component.html>

<mat-grid-tile [colspan]=”( cardLayout | async )?.table.cols” [rowspan]=”( cardLayout | async )?.table.rows”>
<app-card title=”Latest Orders”>
<app-orders-table></app-orders-table>
</app-card>
</mat-grid-tile>

Adding Data To The Table

Like with charts, you can add data to the table in the ngOnInit method from a service. Additionally, you will need to modify your table’s generated data source to consume data from the service. To start off, inject the service in the table’s class constructor. Let’s take the example of a table listing the latest orders for this dashboard. To get data for the table, let’s inject the OrderService in the OrdersTableComponent constructor, change the MatTable type assertion of the table view child, and amend the list of displayed columns to reflect an order interface. If you’re interested in the data being added to the table, you can find it here. The last thing involves getting the total length of the data items available to be used to set the total in the table’s <mat-paginator>.

// orders-table.component.ts
import { OrderService } from ‘../orders.service’;
import { Order } from ‘../order’;

export class OrdersTableComponent implements AfterViewInit, OnInit {

@ViewChild(MatTable) table: MatTable;
dataLength: number;

displayedColumns = [
“id”,
“date”,
“name”,
“status”,
“orderTotal”,
“paymentMode”,
];

constructor(private orderService: OrderService){}

ngOnInit() {
this.datasource = new OrdersTableDataSource(this.orderService);
this.orderService.getOrderCount().subscribe({
next: orderCount => {
this.dataLength = orderCount;
},

});
}

}

Next, we’ll need to modify the OrdersTableDataSource class to accept the OrderService as a parameter in its constructor. We’ll have to modify its connect and destroy methods as well. The connect method connects the data source to the table and updates the table when new data items are emitted from the stream it returns, in this case, an orders array observable. The dataMutations constant combines the first data load, pagination, and sorting events into one stream for the table to consume. Pagination and sorting are handled by the OrderService server-side. So we need to pass the offset and page size from paginator and the active sort field and sort direction of the sort property to the getOrders method of the OrderService. The disconnect method should be used to close any connections made and release resources held up in the connect method.

// orders-table.datasource.ts

export class OrdersTableDataSource extends DataSource<Order> {
paginator: MatPaginator;
sort: MatSort;

constructor(private orderService: OrderService) {
super();
}

connect(): Observable<Order[]> {
const dataMutations = [
of(‘Initial load’),
this.paginator.page,
this.sort.sortChange
];

return merge(…dataMutations).pipe(mergeMap(() => {
return this.orderService.getOrders(
this.paginator.pageIndex * this.paginator.pageSize,
this.paginator.pageSize,
this.sort.active,
this.sort.direction
);
}));
}

disconnect() {}
}

In the orders table template, insert the new columns and bind the length property of <mat-paginator> to the dataLength property. For the status column, use a <mat-chip> element for better visualization of the order status. To have access to <mat-chip>, add the MatChipsModule as an import to AppModule.

<!– orders-table.component.html –>
<div class=”mat-elevation-z8″>
<table mat-table class=”full-width-table” matSort aria-label=”Elements”>
<!– Id Column –>
<ng-container matColumnDef=”id”>
<th mat-header-cell *matHeaderCellDef mat-sort-header>Id</th>
<td mat-cell *matCellDef=”let row”>{{row.id}}</td>
</ng-container>

<!– Date Column –>
<ng-container matColumnDef=”date”>
<th mat-header-cell *matHeaderCellDef mat-sort-header>Date</th>
<td mat-cell *matCellDef=”let row”>{{row.date | date }}</td>
</ng-container>

<!– Name Column –>
<ng-container matColumnDef=”name”>
<th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th>
<td mat-cell *matCellDef=”let row”>{{row.name}}</td>
</ng-container>

<!– Order Total Column –>
<ng-container matColumnDef=”orderTotal”>
<th mat-header-cell *matHeaderCellDef mat-sort-header>Order Total</th>
<td mat-cell *matCellDef=”let row”>{{row.orderTotal | currency}}</td>
</ng-container>

<!– Payment Mode Column –>
<ng-container matColumnDef=”paymentMode”>
<th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Mode</th>
<td mat-cell *matCellDef=”let row”>{{row.paymentMode}}</td>
</ng-container>

<!– Status Column –>
<ng-container matColumnDef=”status”>
<th mat-header-cell *matHeaderCellDef mat-sort-header>Status</th>
<td mat-cell *matCellDef=”let row”>
<mat-chip-list>
<mat-chip color=”{{ row.status == ‘delivered’ ? ‘primary’ : ( row.status == ’shipped’ ? ‘accent’ : ‘warn’ ) }}” selected>
{{row.status}}
</mat-chip>
</mat-chip-list>
</td>
</ng-container>

<tr mat-header-row *matHeaderRowDef=”displayedColumns”></tr>
<tr mat-row *matRowDef=”let row; columns: displayedColumns;”></tr>
</table>

<mat-paginator #paginator [length]=”dataLength” [pageIndex]=”0″ [pageSize]=”5″ [pageSizeOptions]=”[5, 10, 15, 20]”>
</mat-paginator>
</div>

Once data has been added to the table, this is what the dashboard will look like:

dashboard with charts and table

Dashboard with charts and table (Large preview)

Creating A Mini Card Component

All that’s left to complete the dashboard is to populate the four small cards that sit at the top. Having smaller summary cards as part of the dashboard makes it easy to highlight brief pieces of information that do not need whole charts or tables. In this example, the four mini cards will display total sales, average order value, the total number of orders, and the number of returning customers that visited the store for the day. This is just an example. These mini cards cannot be generated like with the navigation, dashboard layout, charts, and the table. They have no schematics. Below we’ll briefly go through how to create them. Although we’re going to add data specific to the example, you can add whatever you want to them or decide to do away with them altogether. To start off, generate the mini-card component, run:

ng g c mini-card -m app –style css

You can find the template for the component linked here and its styling here. This component has eight input properties that you can find out how to add here. To get data to the mini card components, inject the service that provides data to them in the DashComponent constructor. Assign data received from the service to a property of the DashComponent. In this instance, we’ll get data from the StoreSummaryService and assign it to the miniCardData property. Here’s how:

// dash.component.ts
export class DashComponent implements OnInit{

miniCardData: StoreSummary[];

constructor(private breakpointObserver: BreakpointObserver, private summaryService: StoreSummaryService) {}

ngOnInit() {
this.summaryService.getStoreSummary().subscribe({
next: summaryData => {
this.miniCardData = summaryData;
}
});
}
}

To add the mini-cards to the dash component and have them populated with data from the service:

<!–dash.component.html–>

<!–Mini Cards–>
<mat-grid-tile *ngFor=”let mc of miniCardData” [colspan]=”( cardLayout | async )?.miniCard.cols”
[rowspan]=”( cardLayout | async )?.miniCard.rows”>
<app-mini-card [title]=”mc.title” [textValue]=”mc.textValue” [value]=”mc.value” [color]=”mc.color” [percentValue]=”mc.percentValue”></app-mini-card>
</mat-grid-tile>

The screenshot below is what the dashboard will look like with the mini cards populated.

dashboard with charts, tables, and mini-cards

Dashboard with charts, tables, and mini-cards. (Large preview)

Putting All Together

In the end, the dashboard component template should contain:

<!– dashboard.component.html –>
<div class=”grid-container”>
<h1 class=”mat-h1″>Dashboard</h1>
<mat-grid-list cols=”{{ ( cardLayout | async )?.columns }}” rowHeight=”200px”>
<!–Mini Cards–>
<mat-grid-tile *ngFor=”let mc of miniCardData” [colspan]=”( cardLayout | async )?.miniCard.cols”
[rowspan]=”( cardLayout | async )?.miniCard.rows”>
<app-mini-card [icon]=”mc.icon” [title]=”mc.title” [value]=”mc.value” [color]=”mc.color” [isIncrease]=”mc.isIncrease” duration=”since last month” [percentValue]=”mc.percentValue” [isCurrency]=”mc. isCurrency”></app-mini-card>
</mat-grid-tile>
<!–Charts–>
<mat-grid-tile [colspan]=”( cardLayout | async )?.chart.cols” [rowspan]=”( cardLayout | async )?.chart.rows”>
<app-card title=”Monthly Revenue”>
<app-annual-sale-chart></app-annual-sale-chart>
</app-card>
</mat-grid-tile>
<mat-grid-tile [colspan]=”( cardLayout | async )?.chart.cols” [rowspan]=”( cardLayout | async )?.chart.rows”>
<app-card title=”Product Sales”>
<app-product-sales-chart></app-product-sales-chart>
</app-card>
</mat-grid-tile>
<mat-grid-tile [colspan]=”( cardLayout | async )?.chart.cols” [rowspan]=”( cardLayout | async )?.chart.rows”>
<app-card title=”Sales by Traffic Source”>
<app-sales-traffic-chart></app-sales-traffic-chart>
</app-card>
</mat-grid-tile>
<mat-grid-tile [colspan]=”( cardLayout | async )?.chart.cols” [rowspan]=”( cardLayout | async )?.chart.rows”>
<app-card title=”Online Store Sessions by Traffic Source”>
<app-store-sessions-chart></app-store-sessions-chart>
</app-card>
</mat-grid-tile>
<!–Table–>
<mat-grid-tile [colspan]=”( cardLayout | async )?.table.cols” [rowspan]=”( cardLayout | async )?.table.rows”>
<app-card title=”Latest Orders”>
<app-orders-table></app-orders-table>
</app-card>
</mat-grid-tile>
</mat-grid-list>
</div>

Here’s what the resultant dashboard contains.

completed dashboard

Completed dashboard (Large preview)

Conclusion

Creating dashboards involves a fair amount of work and planning. A way to make building them faster is to use the various schematics provided by Angular Material and ng2-charts. With these schematics, running a command will generate a wholly complete component and can result in having a dashboard up and running fairly quickly. This leaves you a lot more time to focus on creating data services and adding them to your dashboard components.

If you want to learn more about some of the schematics provided by Angular Material, visit material.angular.io, and for those provided by ng2-charts, visit their site linked here.

Smashing Editorial
(ra, yk, il)

Popular Design News of the Week: July 20, 2020 – July 26, 2020

Original Source: https://www.webdesignerdepot.com/2020/07/popular-design-news-of-the-week-july-20-2020-july-26-2020/

Every week users submit a lot of interesting stuff on our sister site Webdesigner News, highlighting great content from around the web that can be of interest to web designers.

The best way to keep track of all the great stories and news being posted is simply to check out the Webdesigner News site, however, in case you missed some here’s a quick and useful compilation of the most popular designer news that we curated from the past week.

4 Design Patterns that Violate “Back” Button Expectations

 

We Designed Something that Couldn’t Work

 

Appydev – Best Hand Picked Tools

 

Dark Mode for all the Things

 

15 Amazing Lego Re-Imagined Star Wars Scenes

 

37 SEO Tips all Web Designers Should Know

 

Medium is not the Home for your Ideas

 

How to Start Designing in Figma

 

Recursive Google Font

 

8 Popular UI Design Trends on Dribbble in 2020

 

Teenyicons — Tiny Minimal 1px Icons

 

Stripe: Building a Developer Cult

 

Fast Design will Kill your Product

 

How to Create a Strong Visual Identity for Digital Products

 

How to Create a Responsive Timeline with Image Thumbnails

 

Reploy – Instant, Shareable Previews of your Product

 

Wavium – Start a Blog and Newsletter in Under 5 Minutes

 

Can a Rebranding Make BMW Immune?

 

Webwaste

 

9 Epic Logo Designs Inspired by Famous Fictional Places

 

Create a Stunning Infographic with these 9 Tips and Tricks

 

How to Create a Web Design Portfolio with no Job Experience

 

5 Essential UX Design Principles that Great Designers Embrace

 

I Don’t Want to Be a Founder and I Don’t Think You do Either

 

Stop Worrying About People Stealing your Ideas

 

Want more? No problem! Keep track of top design news from around the web with Webdesigner News.

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;}

Raw Design Inspiration: Hand-picked on Dribbble

Original Source: http://feedproxy.google.com/~r/abduzeedo/~3/LROo5HHoMXI/raw-design-inspiration-hand-picked-dribbble

Raw Design Inspiration: Hand-picked on Dribbble
Raw Design Inspiration: Hand-picked on Dribbble

AoiroStudio07.26.20

We are back with another abdz. ‘Raw Design Inspiration’ No theme, absolutely ‘raw’ inspiration. As you may have been aware, inspiration is one of the biggest fuels in my everyday life. Whatever it is for life and work balance, it comes in many shapes and forms. For me, I do appreciate a good surf on Dribbble. It’s all about how we consume our feeds, I noticed a shift of change from designers on sharing their work on social media platforms like Instagram. I might be an old-timer but I am not too keen on sharing work for likes and shares, I do enjoy the good ‘old’ Dribbble. It’s always gratifying and you usually do find something to spark your mind and inspiration.

The concept of ‘Raw’ is to randomize what inspires me to kick off my week, maybe it could have the same effect on you. This is reasonably an homage to abdz. daily inspiration series. It’s an experiment, and we’ll see how it goes. If you do have a suggestion, you can submit your work.

More on https://dribbble.com

-

By Jona Dinges

By DStudio™

Empty UI gradient color app design empty space empty state mobile ui mobile app ios app ios card ui branding user experience design typography white product design clean ui-ux ux ui

By Yoga Perdana

Zebra Logo animal horse zebra branding logo

By Udhaya Chandran

By Anton Zaderaka

By Craftwork

Boom Illustrations + UI = 🚗 flying cinema4d png startup project elements ui design landing application presentation website web app scene colorful bright illustrations 3d

By MonpixDesign

Food Delivery App mobile fruits fruit food uiux mobile app mobile ui mobile app design ecommerce design app design ecommerce app ecommerce app ux design ui ui design minimal food delivery app

By Asish Sunny

Payment app clean ui trending cards ui credit cash hire freelancer wallet expence income finances web design website dark ui light ui mobile ui clean ux ui

By Lelevien

6833adbf09b00f6ad03a8b09509625e8

By B®andits

Play With Type - B Studio studio minimal branding logo brandits typeface geometric monogram letter typography type play

By Farzan Faruk 👑

watchOS 6 Landing Page - Mobile Concept minimal app design applepencil apple ios mockup apple watch design responsive design smartwatch apple watch 2018 trends ui ux website design product web design landing page homepage ecommerce website

By Sèrgi Mi

Mobile Banking graph balance payment pay illustration banking concept bank app kawaii design cards light mobile ui

By catalyst

music instruments... 🎵🎶🎹🎤🎺🎻🎷🎸🥁 concert cartoon logo icon illustration player musical trumpet violin piano drum song sing sound electric accoustic guitar microphone intrument music

By Laura Lhuillier ⎪ Arual ☺︎

Bottles collection 💧 packagingdesign branding moutain forest aquatic jungle adobe dimension bottle mockup bottle design animal kids illustration illustration art illustrator illustration

By MD Mahfuj

Niox | N letter logo design gradient logo modern logo logo design identitydesign website logo mark n letter logo n letter logos logo illustrator identity branding free logo mockup flat creative logo app vector logo process free logo

By David Kovalev ◒

Photos not flat logo branding agency unfold neuomorphism neuomorphic skeumorphism skeumorphic 3d soft soft3d fun flower colorful photo photos iconset icons icon apple

By UI8

Macbook Pro Mockup - 4K Freebie freebie 4k 3d sketch psd mockup apple macbook

By Benjamin Oberemok

Ping-pong logo design icon symbol mark unfold game paddle rackets table tennis tennis ping pong logo concept fun branding logo

By Fabio Sasso

1c124982a41fa19abb12f03f312ac9a5

By Nathan Riley

 


The best cameras for beginners in 2020

Original Source: http://feedproxy.google.com/~r/CreativeBloq/~3/nugt27eZSlI/best-cameras-for-beginners

The best camera for beginners allow creatives to expand their skills in all sorts of ways. You might be looking to add photography to the services you offer your clients, or find a stylish new way to show off your portfolio. Maybe you want to start vlogging to take your followers behind the scenes of your work – or, hey, perhaps you just want your Insta to pop a little more. There's no shame in that.

Whatever the reason you want to take more pictures, it's best to pick up one of the best cameras for beginners rather than relying on your smartphone. This is because there are certain advantages to cameras that mean they'll always outpace even the latest, most sophisticated smartphone cameras. For more details, jump to what to consider when buying a camera section. 

If you've already got some photography skills, check our our roundup of what we consider the best cameras for all levels to be. And while you're getting kitted out, why not explore our guides to the best memory cards and the best camera bags too.

All of the cameras we've selected for this guide are suited to photography novices, while still offering the capacity to grow with you as you improve. Let's get started.

The best cameras for beginners available now

It’s particularly easy to get up and running with the Nikon D3500. As well as an ‘intelligent’ fully automatic mode, there are wide-ranging scene modes and effects to choose from. More uniquely, there’s a Guide shooting mode, which serves as a kind of interactive photography course. There’s no shortage of quality either, with a high-performance 24.2MP image sensor and processor, a generous ISO (sensitivity) range, speedy 5fps maximum burst rate and a high-resolution LCD screen. 

However, it’s not a touch-sensitive screen and lacks a tilt or pivot facility. Another drawback is that autofocus is relatively slow in live view and movie capture modes but, overall, the D3500 is currently the most appealing beginners’ camera on the market.

The Canon EOS 250D is the first entry-level DSLR to feature 4K movie capture, and it replaces the popular EOS 200D in Canon’s lineup. Indeed, the Dual Pixel CMOS autofocus system for live view and movie modes, inherited from its predecessor, makes the camera particularly good for tracking action when shooting video. The virtually silent autofocus performance of the 18-55mm kit lens is a further bonus.

Not just for video, the 250D is a very accomplished package for stills. It's beginner-friendly with optional Guided User Interface and Creative Assist modes, which work seamlessly with the fully articulated touchscreen. The camera is also well able to grow with you as you learn new skills and techniques, Canon’s excellent Quick menu giving intuitive and instant access to important settings.

One of the most compact and lightweight DSLRs on the market, the 250D is a camera you can take anywhere and everywhere. Our only real criticism is that, in viewfinder-based stills shooting rather than live view mode, the autofocus system is fairly basic. There are only nine AF points and only one of them is cross-type, able to resolve detail in both horizontal and vertical planes.

Fujifilm's mirrorless cameras not only look fantastic, with cool retro styling that has been a hit with photographers for going on a decade now, but they're also some of the best shooters on the market. The Fujifilm X-T200 is one of the newer models, designed for entry-level users who want room to grow their skills and shoot high-quality images and videos. Its upgraded sensor produces a wide dynamic range and pleasingly low noise, and this combines well with Fuji's Film Simulation modes to produce images with real pop.

The X-T200 shoots 4K video in impressive quality, and its articulated touchscreen allows you to get creative with your shooting angles. Having access to the stable of pin-sharp Fujifilm X-mount lenses is also no bad thing, and ensures you'll have plenty of room to grow and explore in your shooting, whatever direction you take it in.

Don't be fooled by the slim dimensions of this compact camera: it's actually an impressive stills-and-video shooting machine, with not only the ability to shoot high-quality Full HD and 4K video, but also to directly livestream it online. Indeed, you might be surprised how many YouTube creators you enjoy shoot a lot of their stuff on the Canon PowerShot G7 X Mark III; it's a popular camera for a reason.

The fast 24-100mm equivalent lens gives you an enormous amount of shooting versatility; no matter the lighting conditions, no matter how distant the subject, you'll probably be able to have a decent crack at capturing it. Video features are also further bolstered by such vital extras as an external mic port, ensuring that your videos will sound as good as they look. The camera feels premium in the hand, and with the LCD that flips around 180 degrees for easy monitoring, you've got a capable machine in all categories.

The best cameras don't have to be digital! Analogue is a great Physical prints of photographs have much more tangible lasting value than digital files, and there's loads of potential for incorporating them into your creative projects. The Polaroid Originals OneStep+ is the best instant-print camera around right now – not only does it produce beautiful square prints in that classic Polaroid style, but it also offers Bluetooth connectivity with a smartphone that give the user access to loads of additional shooting modes like Double Exposure, Light Painting, Noise Trigger and more.

Full of retro charm, the OneStep+ is well-designed and easy to use, with a powerful flash and twin lenses, one for general shooting, the other for portraits and close-ups. It's great value at the price, though bear in mind that film is an ongoing expense, coming in packs of ten that will generally set you back £10-15. Buy in bulk if you can and you'll definitely make some savings.

There have been plenty more cameras released in Sony's a6000 series since this one, so why have we included it? Well, this is a still a fantastic machine in its own right: a fast-shooting, lightweight and dependable mirrorless camera, with an APS-C sensor and a sophisticated autofocus system. A beginning photographer who wants a solid foundation on which to grow and develop their skills will find the a6000 offers all of this and more. Plus, with all the subsequent models that have been released, this camera can now be picked up for an absolute bargain price.

Equipped with a powerful 24.3 APS-C sensor, the Sony a6000 is an E-mount camera, meaning there's a fantastic range of lenses to choose from in addition to the bundled 16-50mm kit lens. This is an ideal choice for those who want to hit the ground running; it doesn't have as many guide modes as other cameras, but if you're prepared to put a little work in, you'll find it to be a rewarding and capable imaging machine.

One of the upsides of Micro Four Thirds mirrorless system cameras is that they tend to be fairly small and lightweight. That’s certainly true of the Olympus E-M10, which is now in its third generation. Although small, it’s impeccably well built and beautifully turned out with classic retro styling. The 14-42mm EZ kit lens is similarly small, with a retractable design that enables compact stowage. 

Even so, it features a built-in motor that enables smooth zooming during video capture. The maximum burst rate for stills is a speedy 8.6fps, although autofocus can be a little slower than in many competing cameras, making it tricky to follow fast-moving action. 4k UHD movie capture is a bonus.

Great for following the action in sports and wildlife photography, the Nikon D5600 has an advanced 39-point autofocus system that boasts auto-area, dynamic-area and 3D-tracking modes. The optional 18-140mm VR kit lens is also particularly suitable for these types of photography, with its 27-210mm ‘effective’ zoom range and competent Vibration Reduction (optical image stabilisation) system. And for when you need to trek into the countryside for shooting wildlife, or stand for long periods at a sporting event, the D5600 won’t weigh you down as it’s one of the lightest and most compact DSLRs on the market. 

The fully articulated touchscreen is an extra bonus, although for live view and video capture, the sensor-based contrast-detection autofocus facility can be painfully slow.

For such a small camera, the Panasonic TZ100 packs in some seriously big specifications and features. It has a 20.1MP 1.0-type sensor that’s physically large for a compact camera, and retains relatively noise-free image quality even at high ISO settings. It also crams in an electronic viewfinder and a high-res, 3.0inch rear screen, plus a 10x zoom lens with an effective range of 25-250mm. 

To keep things steady, there’s optical image stabilisation for stills and 5-axis hybrid stabilisation for video capture. You can also shoot at 4k UHD for both stills and video, with a frame rate of up to 30fps. For full-resolution stills, the burst rate is still speedy at 10fps. 

Clever tricks include ‘post-focus’, which enables you to capture a burst of stills with automatically transitioning focus distances, and select the frame with the ideal focus point afterwards.

Like other ‘tough’ compact cameras on the market, this Olympus Tough TG-5 is designed to take the knocks. It can withstand being submerged in water to a depth of 15 metres, dropped from a height of 2.1 metres and frozen to -10 degrees Celsius. If you’re feeling particularly mean, you can even try crushing it with a 100kg weight, and it’ll still keep on working. 

All in all, it’s a great camera for everything from skiing down mountains to snorkelling in the sea. The maximum burst rate is a similarly action-packed 20fps, and you can also capture 4k UHD movies. The 4x optical zoom lens adds versatility, as do the built-in macro and microscopic modes. To take things even further, a range of optional accessories includes fisheye and telephoto lens converters. While Olympus has since released a Tough TG-6, we'd say this model is the best pick for beginners' offering basically the same package (the new version has an identical sensor and lens; really the only difference is some new modes) for a better price,

The best camera for beginners: What to consider

As mentioned above, cameras will always have certain advantages over smartphones. These include larger sensors, which mean the cameras perform better in low light, as well as massive improvements in the matter of lenses. Whether you're using a DSLR or mirrorless camera that lets you swap lenses depending on the situation, a zoom-equipped compact that can get close to a subject, or even a fixed-focal-length compact that's been engineered for optical perfection, you're guaranteed to have something superior to the lens on the back of your phone. Or the front, for that matter – and thanks to many cameras now having flip-out screens, your selfie game can step up considerably.

Then there's also the fact that cameras can burst-shoot faster for capturing quick-moving subjects, have more sophisticated autofocus systems, and tend to offer higher resolutions that allow you to make larger physical prints of your images. There's no doubt about it – a camera is the way to go!

The best type of camera for beginners 

First, let's look at the different types of camera available for beginners. If your priorities are simplicity and portability, there’s a lot to be said for a small point-and-shoot camera that you can slip into your daily bag or even a spare pocket. These cameras will have a lens fixed on the front, so while you won't be able to use any focal length that isn't specified on the box, most models will offer a respectable zoom range to work with. There will generally also be a built-in flash, and possibly a viewfinder that helps you compose your shots.

A more versatile option is a 'system' camera, which consists of a separate body and interchangeable lenses. Once you're equipped with two or three lenses, you can shoot anything from portraiture and still life, to action sports and wildlife, or sweeping landscapes and architecture, getting great results every time. 

They start small, with mirrorless or compact system cameras. These tend to be portable and offer faster shooting speeds than their larger siblings, DSLRs. However, don't count DSLRs out, as they are able to offer an optical viewfinder that gives you an unadulterated 'through-the-lens' view of what you're shooting. They also tend to be better weather-sealed and equipped with chunkier handgrips for a secure hold.

Also worth considering are instant print cameras! Analogue is back in a big way, and there's something to be said for a camera that doesn't necessitate messing about with memory cards and hard drives, and just spits out an instant physical print. If your creative work is more tactile/physical (perhaps incorporating collage) then this is definitely a viable option. 

Finally, there are also 'tough' cameras, which have smaller sensors than mainstream compacts, but are heavily waterproofed and can survive rough conditions.

But which to pick? Well, it depends on what you need. Do you want something small and portable or hardy and weatherproof? Are you likely to be shooting video as well as stills? Do you see yourself buying more lenses, or would you prefer a single package that does it all? The answers to all these questions will affect which camera is best for you.

Read more:

The best full-frame cameras in 201915 ways to improve your photography skillsThe best monitors for photo editing

20+ Weird And Unusual USB Products

Original Source: https://www.hongkiat.com/blog/weird-and-unusual-usb-products/

That USB port on your PC is not just for connecting USB flash drives or USB data cables. It can also power some mini gadgets. From mug warmers and mini sewing machines to mini washing machines, you…

Visit hongkiat.com for full content.

10 Actionable Instagram Tips and Tricks

Original Source: https://www.hongkiat.com/blog/useful-instagram-tips-tricks/

Instagram is one of the popular social networks for everyone — influencers as well as brands. According to the Pew Research Center, 37% of adults in the US use Instagram with 63% of them using…

Visit hongkiat.com for full content.

Fun & Games by Bullpen

Original Source: http://feedproxy.google.com/~r/abduzeedo/~3/iEQq6exLie0/fun-games-bullpen

Fun & Games by Bullpen
Fun & Games by Bullpen

abduzeedo07.22.20

Bullpen, an independent creative studio based in NYC creating engaging content through design & animation, shared an awesome motion design project with us. Fun & Games, is a tongue in cheek look at the games we design and give our children. It’s all fun & games. Until it isn’t. Developed over the course of a year, this piece is inspired after time spent playing with our own children. While we certainly take things to an extreme, we believe there is an underlying truth that is interesting to think about. We hope you enjoy it!

Credits

Direction: Bullpen
Design: Elliot Lim
3D: Aaron Kemnitzer
Music: Lullatone “how I broke my parent’s record player (when I was five)”
Stills

Image may contain: coin


How To Create a Responsive Timeline with Image Thumbnails

Original Source: http://feedproxy.google.com/~r/1stwebdesigner/~3/hky9PFuhQro/

In this tutorial you will learn how to create a responsive timeline for a set of related events you wish to display in a chronological (or reverse chronological) sequence. This can be used to display significant company milestones, news or personal events. I have used personal travel events as an example in this post. Here’s what you will be able to create by the end of this tutorial.

Responsive Timeline - Desktop View

Desktop View

 

Responsive Timeline - Small Tablets / Mobile Landscape View

Small Tablets / Mobile Landscape View

 

Responsive Timeline - Mobile Portrait View

Mobile Portrait View

 

You need to have some basic knowledge of HTML and CSS to follow along. Let’s get started.

Millions of Fonts, Themes, Graphics: Starting at ONLY $16.50 per Month

Web Fonts

Web Fonts
8,000+ Fonts

WordPress Themes

WordPress Themes
1,200+ Themes

Graphic Assets

Graphic Assets
32,000+ Graphics

DOWNLOAD NOW
Envato Elements

 

Setting up

Create a blank HTML document and name it index.html. Add the basic HTML skeleton. If you use Visual Studio Code, all you need to do is type “!” and hit enter. You will end up with this.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>

</body>
</html>

I have used the font ‘Noto Sans’ – with font weights 300 and 700. So add the following line below the title tag to embed this font using Google fonts.

<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;700&display=swap" rel="stylesheet">

Create your stylesheet and name it style.css. Link the stylesheet to your HTML document below the Google fonts CDN link using:

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

The bare bones structure

Let’s first create the timeline structure, and in the next part we will add and style the content.

HTML

Add this to your markup:

<div class="timeline">
<div class="container container-left">
<div class="content"></div>
</div>
<div class="container container-right">
<div class="content"></div>
</div>
<div class="container container-left">
<div class="content"></div>
</div>
</div>

CSS

In style.css, begin with some common styles for all elements:

* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

Add these styles to the body element:

body {
background-color: #EDF2F7;
font-family: ‘Noto Sans’, sans-serif;
font-size: 1em;
color: #4A5568;
}

To the timeline, add the following styles. Let’s restrict the maximum width to 1200px and center the content using margin.

.timeline {
position: relative;
max-width: 1200px; /* Restrict the width on large screens */
margin: 0 auto; /* Center the content */
padding: 30px;
}

Now, we can use the ::after pseudo element to create that actual line in the center for timeline. Add these styles:

.timeline::after {
content: ”;
position: absolute;
width: 6px;
background-color: white;
top: 0;
bottom: 0;
left: 50%;
margin-left: -3px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}

Width of the line is 6px. Hence, we have used left:50% and margin-left: -3px to position the line at the exact center. Read more about centering an element using absolute position.

You will now see a very tiny line at the top of your webpage, vertically centered. As we add some content, this line lengthens.

Let’s style the left and right containers that hold the timeline elements.

.container {
position: relative;
width: 50%;
}
.container-left {
left: 0;
}
.container-right {
left: 50%;
}

You will still not see anything on the web page until we style the .content element within.

.content {
padding: 30px;
background-color: white;
position: relative;
border-radius: 6px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}

You should be able to see this now.

Responsive timeline so far

 

Our timeline is taking shape. Let’s add those tiny arrow marks pointing to the line using a ::before pseudo element.

.container .content::before {
content: " ";
height: 0;
position: absolute;
top: 40px;
width: 0;
z-index: 1;
border: medium solid white;
right: -10px;
border-width: 10px 0 10px 10px;
border-color: transparent transparent transparent white;
}

This will add all arrow marks pointing to the right, positioned to the right edge of the box. But for the boxes on the right, we need an arrow pointing to the left and positioned to the left. So, change of all this to:

.container .content::before {
content: " ";
height: 0;
position: absolute;
top: 20px;
width: 0;
z-index: 1;
border: medium solid white;
}
.container-left .content::before {
right: -10px;
border-width: 10px 0 10px 10px;
border-color: transparent transparent transparent white;
}
.container-right .content::before {
left: -10px;
border-width: 10px 10px 10px 0;
border-color: transparent white transparent transparent;
}

Read more about how to create these CSS triangles using borders. Of course the output now looks a little odd because the boxes are sticking to the line. Add some padding to the container to space them out.

.container-left {
/* Existing styles here */
padding-right: 70px;
}
.container-right {
/* Existing styles here */
padding-left: 70px;
}

This is perfect.

responsive timeline with arrows

 

Adding and styling content

Let us first add the images and position them on the “line”.

HTML

Change your markup to this, by adding 3 div elements with background images.

<div class="timeline">
<div class="container container-left">
<div class="image" style="background-image:url(‘https://images.pexels.com/photos/307008/pexels-photo-307008.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=100’)"></div>
<div class="content"></div>
</div>
<div class="container container-right">
<div class="image" style="background-image:url(‘https://images.pexels.com/photos/210012/pexels-photo-210012.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=100’)"></div>
<div class="content"></div>
</div>
<div class="container container-left">
<div class="image" style="background-image:url(‘https://images.pexels.com/photos/2104152/pexels-photo-2104152.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=100’)"></div>
<div class="content"></div>
</div>
</div>

As you can see, I have directly linked 3 images from Pexels. You can choose to include your own.

CSS

Let’s add some size and shape to this image div.

.image {
width:90px;
height:90px;
background-size:cover;
background-position:center;
border:solid 5px #ffffff;
border-radius:50px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}

Now position them centered on the line, appearing next to boxes.

.image {
position: absolute;
}
.container-left .image {
right: 0;
margin-right: -45px;
}
.container-right .image {
left: 0;
margin-left: -45px;
}

But the images appear behind the line! This is easily fixed with some z-index.

.timeline::after {
/* Existing styles here */
z-index: 1;
}
.image {
/* Existing styles here */
z-index: 2;
}

Don’t mind the images overlapping each other right now. It will be fixed when we add some content within the boxes. But if your content is going to be very little, add a minimum height to the container.

.container {
/* Existing styles here */
min-height: 120px;
}

Next, add the actual content.

HTML

Add this markup within each .content block. Change the text as you wish.

<span>July 2020</span>
<h2>Visit to Spain</h2>
<p>
Et hinc magna voluptatum usu, cum veniam graece et. Ius ea scripserit temporibus, pri cu harum tacimates neglegentur. At adipisci incorrupte nam. Cu qui sumo appareat constituto.
</p>

CSS

We need to position the arrow marks such that they align with the center of the image.

.container .content::before {
/* Existing styles here */
top: 35px;
}

Align the text on left side boxes to the right and right side boxes to the left.

.container-left {
/* Existing styles here */
text-align: right;
}
.container-right {
/* Existing styles here */
text-align: left;
}

Now some styles for the actual content.

.content span {
color: #2C7A7B;
font-size: 1.1em;
font-weight: bold;
}
.content h2 {
font-size: 1.8em;
padding-top: 5px;
}
.content p {
line-height: 1.6;
padding-top: 5px;
}

Isn’t this neat? Great! Now resize your browser window to make it smaller, and things start to look messy when the screen size is too small.

Make it responsive

In smaller screens, when there are boxes on both sides of the line, the boxes become too narrow. Time to add some media queries. Let’s add a breakpoint at 767px width and position both the boxes on one side when the screen width is smaller than this width.

@media screen and (max-width: 767px) {
/* Add styles to change the behaviour for screens smaller than 767px width */
}

First, position the line to the left of the page. Add the below styles within the media query:

.timeline::after {
left: 65px;
}

Make the containers full width and position them correctly by overriding the previous styles.

.container {
width: 100%;
padding-left: 100px;
padding-right: 0px;
}
.container-right {
left: 0%;
}
.container-left {
text-align: left;
}

Add some top margin to all the containers, except the first.

.container {
/* Existing styles here */
margin-top: 30px;
}
.container:first-of-type {
margin-top: 0px;
}

Override image styles to position them on the line.

.container .image {
left:-10px;
top: 0px;
margin-left: 0;
margin-right: 0;
}

The arrows on the “left” boxes need to change position and direction.

.container-left .content::before {
left: -10px;
right: auto;
border-width: 10px 10px 10px 0;
border-color: transparent white transparent transparent;
}

This is what we have now:

Timeline responsive view one

 

Further reduce the screen size and you will notice that on really small screens (less than 400px width), the boxes again get narrow. Which is why, below 480px, let’s push the containers below the image giving them full screen’s width to occupy.

@media screen and (max-width: 480px) {
.container {
padding-left: 0px;
padding-top: 105px;
}
}

To prevent the line from appearing on top of the boxes instead of below, just add a z-index to the container and give a higher value than the “line”.

.container {
/* Existing styles here */
z-index: 3;
}

The only pending thing right now is to position the arrows on top and make them point upwards.

.container .content::before {
left: 25px;
top: -10px;
border: medium solid white;
border-width: 0 10px 10px 10px;
border-color: transparent transparent white transparent;
}

You got it! Resize your browser making it smaller and larger to see how responsive your timeline is. Go ahead and customize it to suit your needs. Just in case you didn’t get this working as expected, download the full source code and feel free to make changes as you wish.

 

Download Source Code

 


In Memory of Flash: 1996-2020

Original Source: https://www.webdesignerdepot.com/2020/07/in-memory-of-flash-1996-2020/

We are gathered here today….

Today I write in memory of Adobe Flash (née Macromedia), something that a bunch of people are actually too young to remember. I write this with love, longing, and a palpable sense of relief that it’s all over. I have come to praise Flash, to curse it, and finally to bury it.

We’ve been hearing about the death of Flash for a long time. We know it’s coming. December 2020 has been announced as the official timeframe for removal, but let’s be real about this: it’s dead. It’s super-dead. It’s people-are-selling-Flash-game-archives-on-Steam dead.

That last bit actually makes me happy, because Flash games were a huge part of my childhood, and the archives must be preserved. Before I’d ever heard of video cards, frames per second, and “git gud”, I was whiling away many an hour on disney.com, cartoonnetwork.com, MiniClip, Kongregate, and other sites, looking for games.

I think we’ve established in my previous work that even as a missionary kid, I did not have a social life.

The Internet itself gave me a way to reach out and see beyond my house, my city, and my world, and it was wonderful. Flash was a part of that era when the Internet felt new, fresh, and loaded with potential. Flash never sent anyone abuse, or death threats. Flash was for silly animations, and games that my parent’s computer could just barely handle, after half an hour of downloading.

I even built my first animated navigation menus in Flash, because I didn’t know any better. At all. But those menus looked exactly like the ones I’d designed in Photoshop, so that’s what mattered to me, young as I was.

That was a part of Flash’s charm, really.

What Flash Got Right
Flash Brought Online Multimedia into the Mainstream

Funny story, JavaScript was only about a year old when Flash was released. While HTML5 and JS are the de-facto technologies for getting things done now, Flash was, for many, the better option at launch. JS had inconsistent support across browsers, and didn’t come with a handy application that would let you draw and animate whatever you wanted.

It was (in part) Flash that opened up a world of online business possibilities, that made people realize the Internet had potential rivalling that of television. It brought a wave of financial and social investment that wouldn’t be seen again until the advent of mainstream social networks like MySpace.

The Internet was already big business, but Flash design became an industry unto itself.

Flash Was Responsive

Yeah, Flash websites could be reliably responsive (and still fancy!) before purely HTML-based sites pulled it off. Of course, it was called by other names back then, names like “Liquid Design”, or “Flex Design”. But you could reliably build a website in Flash, and you knew it would look good on everything from 800×600 monitors, to the devastatingly huge 1024×768 screens.

You know, before those darned kids with their “wide screens” took over. Even then, Flash still looked good, even if a bunch of people suddenly had to stop making their sites with a square-ish aspect ratio.

Flash Was Browser-Agnostic

On top of being pseudo-responsive, the plugin-based Flash player was almost guaranteed to work the same in every major browser. Back in a time when Netscape and Internet Explorer didn’t have anything that remotely resembled feature parity, the ability to guarantee a consistent website experience was to be treasured. When FireFox and Chrome came out, with IE lagging further behind, that didn’t change.

While the CSS Working Group and others fought long and hard for the web to become something usable, Flash skated by on its sheer convenience. If your site was built in Flash, you didn’t have to care which browsers supported the <marquee> tag, or whatever other ill-conceived gimmick was new and trendy.

Flash Popularized Streaming Video

Remember when YouTube had a Flash-based video player? Long before YouTube, pretty much every site with video was using Flash to play videos online. It started with some sites I probably shouldn’t mention around the kids, and then everyone was doing it.

Some of my fondest memories are of watching cartoon clips as a teenager. I’d never gotten to watch Gargoyles or Batman: The Animated Series as a young kid, those experience came via the Internet, and yes… Flash. Flash video players brought me Avatar: The Last Airbender, which never ever had a live action adaptation.

Anyway, my point: Flash made online video streaming happen. If you’ve ever loved a Netflix or Prime original show (bring back The Tick!), you can thank Macromedia.

What Flash Got Wrong

Obviously, not everything was rosy and golden. If it was, we’d have never moved on to bigger, better things. Flash had problems that ultimately killed it, giving me the chance, nay, the responsibility of eulogizing one of the Internet’s most important formative technologies.

Firstly, it was buggy and insecure: This is not necessarily a deal-breaker in the tech world, and Microsoft is doing just fine, thank you. Still, as Flash matured and the code-base expanded, the bugs became more pronounced. The fact that it was prone to myriad security issues made it a hard sell to any company that wanted to make money.

Which is, you know, all of them.

Secondly, it was SEO-unfriendly: Here was a more serious problem, sales-wise. While we’re mostly past the era when everyone and their dog was running a shady SEO company, search engines are still the lifeblood of most online businesses. Having a site that Google can’t index is just a no-go. By the time Google had managed to index SWF files, it was already too late.

Thirdly, its performance steadily got worse: With an expanding set of features and code, the Flash plugin just took more and more resources to run. Pair it with Chrome during that browser’s worst RAM-devouring days, and you have a problem.

Then, while desktops were getting more and more powerful just (I assume) to keep up with Flash, Apple went and introduced the iPhone. Flash. Sucked. On. Mobile. Even the vendors that went out of their way to include a Flash implementation on their smartphones almost never did it well.

It was so much of a hassle that when Apple officially dropped Flash support, the entire world said, “Okay, yeah, that’s fair.”

Side note: Flash always sucked on Linux. I’m just saying.

Ashes to Ashes…

Flash was, for its time, a good thing for the Internet as a whole. We’ve outgrown it now, but it would be reckless of us to ignore the good things it brought to the world. Like the creativity of a million amateur animators, and especially that one cartoon called “End of Ze World”.

Goodbye Flash, you sucked. And you were great. Rest in peace. Rest in pieces. Good riddance. I’ll miss you.

 

 

Featured image via Fabio Ballasina and Daniel Korpai.

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;}