What Makes An Amazing Logo Designer & Where To Find One?

Post pobrano z: What Makes An Amazing Logo Designer & Where To Find One?

An outstanding logo reflects the tone, vision, and values of your company or brand. It is your first impression to the outside world, one that can affect a client’s brand awareness, buying decision, and general attitude towards a certain product. Ensuring your business has an appealing and effective identity is critical.

With many logo design services dishing out substandard logos in bulk, finding a competent designer who can come up with amazing concepts and create wonderful designs can prove to be a daunting task. Below are the top qualities of a competent logo design professional and where to find one.

1. An Outstanding Portfolio

If you want to know the skill level of your prospective logo designer, look at their previous identity projects. This way, you will know what to expect from the designer in terms of quality, reliability, and professionalism. Positive testimonials and reviews from former customers and colleagues will tell you whether a particular designer can be relied on or not. Verify the validity of the reviews and testimonials by checking the web address or contacting the company.

2. Effective Communication Skills

The primary job of a designer is to communicate your story, ideas, and brand. However, the professional also needs excellent communication skills to explain, charm, and negotiate for their work. They should be able to maintain professionalism in tricky circumstances and to be transparent with you on the brief. The logo design expert should respond to your questions professionally and courteously.

3. A Holistic Design Process

Does your designer follow a holistic logo design process or do they produce logos like fast food? A reliable design process can’t take less than 48 hours to complete. Consider how long you want your logo to be relevant – do you want to work with a designer who will research and design it in under 48 hours? A competent designer should strive to understand the nature and marketing needs of your business before embarking on the design process. They should be conversant with designs that are currently trending. There is no definite time frame since logo design needs vary from one client to another, but for small and medium companies, a rough estimate would be anywhere from 2 to 6 weeks.

4. Knows the Value of Color, Typeface, & Icon Design

An amazing logo designer understands the importance of using meaningful colors. Various colors and shades can impact on people in various ways due to color associations. Green is linked to the environment, development, and renewal, and it is ideal for businesses with garden centers or go green initiatives. However, people also associate green with sickness, and it would be a poor option for stomach relief medications.

Your designer should use proper typeface. They may go for bold, exhilarating fonts, or feminine wavy fonts, but they should avoid harsh, bulky lettering when dealing with a ballet company. They should also avoid graceful, faint lettering when dealing with a football team. When designing the icon, the designer should incorporate some elaborate features without compromising the ability of the logo to make a swift statement.

5. Research and Analytical Skills

Competent designers conduct thorough research to familiarize themselves with new trends in the logo design industry. They also analyze the market to unearth new ideas that they can incorporate into their design. They also compare their designs with those of their competitors to identify concepts they can tweak a bit to suit the needs of their clients.

6. Academic Qualification

A good designer must have completed a course, preferably a degree in the relevant field, at a recognized university. Working with an expert who has both theoretical and practical knowledge ensures that you will get quality service.

ONEOUT Creative is one of the top designers across the globe. They specialize in creating outstanding customized professional logos, which outshine logos from competitors. Located in Australia, these reputable Brisbane logo designers meet all the qualities that make a great logo designer. Apart from having an unparalleled creative design experience, they also have a wealth of marketing and brand building knowledge. Therefore, they will not only give you a logo that you’ll cherish but also professional advice to help you market your business.

Where Do You Find a Good Logo Designer?

  • Create a Budget
    Ideally, the cost of appealing logo designs, which catch the attention of your clients quickly, is anywhere from a few hundred to thousands of dollars. Thus, having a budget allows you to know how much you are comfortable spending on the logo.
  • Google Search and Narrow Your Options
    Google search designers available within your locality and go through reviews of every brilliant company you come across. This way, you can narrow your search to a few companies to simplify the selection process.
  • Compare Portfolios
    Portfolios are essential materials that can help you do an up-close assessment of the skills of different designers and the quality of their designs. Check if they have the logo designs you are looking for in their portfolio. Apart from the quality, assess the logos’ aesthetical details to establish whether it adheres to the current trends or not. After doing a thorough comparison of various portfolios, you should select two or three that appeals more to you.
  • Design Affiliations
    Are your potential designers affiliated with any publications or design associations? Affiliation to at least one professional association is an indication that they are committed to their craft.
  • Work Closely with Your Designer
    A qualified and experienced designer usually carries out a face-to-face session whose purpose is to understand the mission, values, and tones of your company or brand. Big brands can respond to these questions quickly and effectively since they already have their brand’s mission statement in mind. However, startups may have a hard time since they are still in the take-off stage. So, know what you want from the designer and cooperate well with them throughout the design process.

With tons of options available, finding the best designer for your unique needs is daunting. You should take time to compare different designers before settling for one. Review their portfolios, logos, reputation, level of experience, and reliability. Use the tips discussed in this article to make your work easier.

The Importance of Image for your Business

Post pobrano z: The Importance of Image for your Business

In our day and age, a company’s image is just as important as the functionality of its products. The fast-paced world we live in, the mushrooming more brands and the overload of information, all require intelligent design processes that ensure a brand’s uniqueness and longevity.
Successful companies such as Apple or Coca-Cola have long proven the paramount status of a brand’s image, and more and more companies are measured first and foremost by their creative accomplishments.

According to a recent Forrester report, businesses that put their main focus on design and customer experience have seen increases in revenue by as much as 36%. In addition, almost half of all design-driven companies have managed to exceed their business goals for the year 2017. This goes to show that the role of design is becoming increasingly important, no matter the size of the business. Here are a few important things to keep in mind when it comes to your company’s image.

Designing a Brand Logo

Design does not only fulfill certain functional needs of a customer but also emotional ones. As a matter of fact, many people make their purchase choices solely based on the design experience. It is what people remember and recognize and how they establish an emotional bond with a specific brand. A brand’s design is therefore a powerful marketing tool and should always be well-considered.

The logo is the most crucial element of a brand’s overall image. It is essentially the face of the company and the icon that stands for everything connected to it. Brand logos should be:

  • Easily recognizable
  • Flexible and adjustable
  • Unique and innovative

The golden rule is: Less is more. Naturally, a brand logo should always be original and stand out from its competitors, yet the simpler the design, the better the logo. Always keep in mind that a brand’s icon will appear in many different places, be put against different backdrops and reproduced in various sizes and formats. Too much detail in the logo’s design will easily be lost. The most successful brand logos are usually known for their simplicity, which makes them instantly recognizable and reproducible.

It is also vital to create an icon that is flexible in the sense that you can make minor alterations over the course of time to keep it up to date. For instance, one might want a “fresher” or “younger” look for their company at a certain point, so make sure this is also feasible with the logo. Choose a contemporary design over a trendy one. Whereas the latter is likely to go out of style within a matter of years, a contemporary design will still be interesting even after a long time. Starbucks, for example, actually dropped all words from its logo in 2011, relying on the iconic mermaid image to represent the brand. Interestingly, Gap attempted to update its logo in 2010, only to revert back to its original design after a public backlash.

Flyers, Posters and Brochures

Despite the almost endless amount of software tools and templates which make it fairly easy to design posters, flyers and other marketing tools, there is much more to creating a truly powerful design. The design should always be:

  • Simple
  • Memorable
  • Inventive
  • Of high quality

For instance, before getting leaflet printing done through a place like print24, make sure to select the highest possible quality for print and paper to increase the design value. This is because anyone accepting a leaflet from someone on the street or finding one in a café definitely won’t be tempted to read the information if the presentation is poor.

The design itself should always be kept basic. An overload of information is not going to have the desired impact, but is most likely going to deter the reader from having a closer look. Nothing should be left to chance and every detail of the design should serve a purpose, from color to layout to font.

Keep in mind that it doesn’t take much to catch the attention of your target audience, as too much information will most likely put them off. Overall, if you think the design of something as trivial as a flyer has no impact on your business, then you’re wrong. Image is everything, and every aspect of your company should be treated equally, from the logo all the way down to a business card.

The Importance of Image for your Business

Post pobrano z: The Importance of Image for your Business

In our day and age, a company’s image is just as important as the functionality of its products. The fast-paced world we live in, the mushrooming more brands and the overload of information, all require intelligent design processes that ensure a brand’s uniqueness and longevity.
Successful companies such as Apple or Coca-Cola have long proven the paramount status of a brand’s image, and more and more companies are measured first and foremost by their creative accomplishments.

According to a recent Forrester report, businesses that put their main focus on design and customer experience have seen increases in revenue by as much as 36%. In addition, almost half of all design-driven companies have managed to exceed their business goals for the year 2017. This goes to show that the role of design is becoming increasingly important, no matter the size of the business. Here are a few important things to keep in mind when it comes to your company’s image.

Designing a Brand Logo

Design does not only fulfill certain functional needs of a customer but also emotional ones. As a matter of fact, many people make their purchase choices solely based on the design experience. It is what people remember and recognize and how they establish an emotional bond with a specific brand. A brand’s design is therefore a powerful marketing tool and should always be well-considered.

The logo is the most crucial element of a brand’s overall image. It is essentially the face of the company and the icon that stands for everything connected to it. Brand logos should be:

  • Easily recognizable
  • Flexible and adjustable
  • Unique and innovative

The golden rule is: Less is more. Naturally, a brand logo should always be original and stand out from its competitors, yet the simpler the design, the better the logo. Always keep in mind that a brand’s icon will appear in many different places, be put against different backdrops and reproduced in various sizes and formats. Too much detail in the logo’s design will easily be lost. The most successful brand logos are usually known for their simplicity, which makes them instantly recognizable and reproducible.

It is also vital to create an icon that is flexible in the sense that you can make minor alterations over the course of time to keep it up to date. For instance, one might want a “fresher” or “younger” look for their company at a certain point, so make sure this is also feasible with the logo. Choose a contemporary design over a trendy one. Whereas the latter is likely to go out of style within a matter of years, a contemporary design will still be interesting even after a long time. Starbucks, for example, actually dropped all words from its logo in 2011, relying on the iconic mermaid image to represent the brand. Interestingly, Gap attempted to update its logo in 2010, only to revert back to its original design after a public backlash.

Flyers, Posters and Brochures

Despite the almost endless amount of software tools and templates which make it fairly easy to design posters, flyers and other marketing tools, there is much more to creating a truly powerful design. The design should always be:

  • Simple
  • Memorable
  • Inventive
  • Of high quality

For instance, before getting leaflet printing done through a place like print24, make sure to select the highest possible quality for print and paper to increase the design value. This is because anyone accepting a leaflet from someone on the street or finding one in a café definitely won’t be tempted to read the information if the presentation is poor.

The design itself should always be kept basic. An overload of information is not going to have the desired impact, but is most likely going to deter the reader from having a closer look. Nothing should be left to chance and every detail of the design should serve a purpose, from color to layout to font.

Keep in mind that it doesn’t take much to catch the attention of your target audience, as too much information will most likely put them off. Overall, if you think the design of something as trivial as a flyer has no impact on your business, then you’re wrong. Image is everything, and every aspect of your company should be treated equally, from the logo all the way down to a business card.

A Basic WooCommerce Setup to Sell T-Shirts

Post pobrano z: A Basic WooCommerce Setup to Sell T-Shirts

WooCommerce is a powerful eCommerce solution for WordPress sites. If you’re like me, and like working with WordPress and have WordPress-powered sites already, WooCommerce is a no-brainer for helping you sell things online on those sites. But even if you don’t already have a WordPress site, WooCommerce is so good I think it would make sense to spin up a WordPress site so you could use it for your eCommerce solution.

Personally, I’ve used WooCommerce a number of times to sell things. Most recently, I’ve used it to sell T-Shirts (and hats) over on CodePen. We use WordPress already to power our blog, documentation, and podcast. Makes perfect sense to use WordPress for the store as well!

What I think is notable about our WooCommerce installation at CodePen is how painless it was, while doing everything we need it to do. I’d say it was a half-day job with maybe a half-day of maintenance every few months, partially based on us wanting to change something.

The first step is installing the plugin, and immediately you get a Products post type you can use to add new products. We’re selling a T-Shirt, so that looks like this:

Note the variations in use for size. We even track inventory at the size level so our T-Shirt printing company knows when to re-print different sizes.

What is somewhat astounding about WooCommerce is that you might need to do very little else. You could set a price, flip on the basic PayPal integration and enter your email, publish the product, and start taking orders.

Or, you could start customizing things and do as much or as little as you want:

  • You could add as many different payment processors as you like. We like using Stripe for credit card processing at CodePen, but also offer PayPal.
  • You could customize the template of every different page involved, or just use the defaults. At CodePen we have very lightly customized templates for the store homepage and product page.
  • You could get very detailed with calculating shipping costs, or use flat rates. We use a flat rate shipping cost at CodePen almost as marketing: same shipping cost anywhere in the world!
  • You could get into integrations, like connecting it with your MailChimp account for further email marketing or Slack account to notify your team of sales.

If you can dream it, you can do it with WooCommerce.

At CodePen, we work with a company called RealThread that actually prints and ships the T-Shirts.

They work great with WooCommerce of course, and the way we set that up is that we use the ShipStation integration and blast the orders into their account there and they handle all the fulfillment from there. There are all sorts of shipping method plugins though for anything you can think of.

Within WooCommerce, we have a dashboard of all the orders, their status, and even tracking information should we need to look something up.

So essentially:

  1. We use WooCommerce
  2. We use the Stripe plugin to take our credit card payments that way
  3. We use the PayPal plugin to take PayPal payments over Braintree
  4. We use the ShipStation plugin to send orders to that system for our fulfillment company to handle

It was quite easy to set up and works great, and it’s comforting to know that we could do tons more with it if we needed to and support is there to help.

The post A Basic WooCommerce Setup to Sell T-Shirts appeared first on CSS-Tricks.

What You Should Know About the Game of Colors When Creating Your Brand

Post pobrano z: What You Should Know About the Game of Colors When Creating Your Brand

Color is one of the most powerful means of communication. Nature uses it to signal us what is dangerous or poisonous, to attract or repel. Each color has its meaning and a special place in our everyday lives. We are used to associating pink with girls, blue with boys and red with a passion but how does the game of colors work in a business setting?  

The basic meaning behind the game of colors 

The emotion that colors evoke has remained strong throughout the years.  

The Color Wheel gives us a definition of the meaning of each color, which can be very useful when you are choosing the main nuance of your brand. 

  • Red is an emotionally intense color and is used to make people take quick decisions. It is associated with energy, power, strength, desire, and Red is used to emphasize a given text or image and it brings them to the foreground. It is part of many national flags and important road signs such as “stop”.
  • Orange is associated with happiness, enthusiasm, creativity, and It stimulates mental activity and is associated with citrus fruits and hence with healthy food. The color is often used to promote toys or food.
  • Yellow is a warm, cheerful color that brings happiness, joy, energy and is associated with intellect. As it grabs the attention, it is a good idea to use yellow for the most important elements of your design. You can use it to promote leisure activities, for example.
  • Green is the color of nature and is highly associated with safety, harmony, growth. You can use it to promote “green” products and safe medical products. Darker green is the color of money so it is very good for a brand associated with finance, banking or Wall Street.
  • Blue symbolizes stability, trust, intelligence and evokes confidence. It is a masculine color and is often used to promote high-tech products.
  • Purple is the symbol of royalty, wisdom, magic. Most of the pre-adolescent children prefer this nuance so it is a good strategy to include it in your brand design if this is your target group.
  • White is often seen as the color of perfection and symbolizes light, purity, goodness. It is often associated with the successful beginning and simplicity. It can be used to advertise safe medical procedures and hospitals or new technologies. It is also a good color for a charity organization.
  • Black evokes power and is associated with elegance, power, and Black can be used as a background to make other colors stand out. It is often used for quite expensive products so including this color in your brand will make it stand out.

 How color defines your brand 

Color defines the feeling that we get towards a certain object no matter if it is part of the nature that surrounds us or is an artificial discovery of mankind. The same associations arise between a given color and a brand. When you think of Coca-Cola, for example, you definitely see red.  Ferrari is yet another brand that makes use of this powerful color. 

A combination of red and yellow is often used by fast food chains. Recently, McDonald’s decided to run away a bit from this combination by adding some green to its main colors as a symbol of their attempt to distinguish themselves from their competitors. 

Handmadewritings who specialize in providing custom writing services use a lot of yellow in their brand design, which as mentioned above is the symbol of intellect and thus they emphasize the intellectual services they provide. The combination of old-fashioned books and a blackboard enhances the meaning of the brand and their position in the educational market. 

Many banks use green, as the symbol of money or the national colors in order to win the trust of their customers. Newspapers and magazines that are established as a solid and trustworthy source of information prefer black in their design as a symbol of their high quality.  

The overall idea is that you should know your customers and the message you want to send them when choosing the colors of your brand. 

The power of color  

There are many studies that reveal the significant role color plays in building a relationship between a potential customer and a given brand. A person needs just 90 seconds to make their decision about another person or a product and the influence of color in this process is between 62% and 90%. This means that you should not underestimate the power of color when designing your website, logo or any other materials related to your brand. Take time to research the market, learn from your competitors and find inspiration in nature in order to come up with the best color combination that will establish your brand on the market. 

Color is emotion and we often choose our favorite brands with our heart but through our eyes. When it comes to design, it is good to consult experienced experts in the field who can give you the best tips when it comes to nuances. Keep in mind the above-written advice as well and you will manage to find the best shade for your brand and play the game of colors with confidence.  

::before vs :before

Post pobrano z: ::before vs :before

Note the double-colon ::before versus the single-colon :before. Which one is correct?

Technically, the correct answer is ::before. But that doesn’t mean you should automatically use it.

The situation is that:

  • double-colon selectors are pseudo-elements.
  • single-colon selectors are pseudo-selectors.

::before is definitely a pseudo-element, so it should use the double colon.

The distinction between a pseudo-element and pseudo-selector is already confusing. Fortunately, ::after and ::before are fairly straightforward. They literally add something new to the page, an element.

But something like ::first-letter is also a pseudo-element. The way I reason that out in my brain is that it’s selecting a part of something in which there is no existing HTML element for. There is no <span> around that first letter you’re targeting, so that first letter is almost like a new element you’re adding on the page. That differs from pseudo-selectors which are selecting things that already exist, like the :nth-child(2) or whatever.

Even though ::before is a pseudo-element and a double-colon is the correct way to use pseudo-elements, should you?

There is an argument that perhaps you should use :before, which goes like this:

  1. Internet Explorer 8 and below only supported :before, not ::before
  2. All modern browsers support it both ways, since tons of sites use :before and browsers really value backwards compatibility.
  3. Hey it’s one less character as a bonus.

I’ve heard people say that they have a CSS linter that requires (or automates) them to be single-colon. Personally, I’m OK with people doing that. Seems fine. I’d value consistency over which way you choose to go.

On the flip side, there’s an argument for going with ::before that goes like this:

  1. Single-colon pseudo-elements were a mistake. There will never be any more pseudo-elements with a single-colon.
  2. If you have the distinction straight in your mind, might as well train your fingers to do it right.
  3. This is already confusing enough, so let’s just follow the correctly specced way.

I’ve got my linter set up to force me to do double-colons. I don’t support Internet Explorer 8 anyway and it feels good to be doing things the „right” way.

The post ::before vs :before appeared first on CSS-Tricks.

A Basic WooCommerce Setup to Sell T-Shirts

Post pobrano z: A Basic WooCommerce Setup to Sell T-Shirts

WooCommerce is a powerful eCommerce solution for WordPress sites. If you’re like me, and like working with WordPress and have WordPress-powered sites already, WooCommerce is a no-brainer for helping you sell things online on those sites. But even if you don’t already have a WordPress site, WooCommerce is so good I think it would make sense to spin up a WordPress site so you could use it for your eCommerce solution.

Personally, I’ve used WooCommerce a number of times to sell things. Most recently, I’ve used it to sell T-Shirts (and hats) over on CodePen. We use WordPress already to power our blog, documentation, and podcast. Makes perfect sense to use WordPress for the store as well!

What I think is notable about our WooCommerce installation at CodePen is how painless it was, while doing everything we need it to do. I’d say it was a half-day job with maybe a half-day of maintenance every few months, partially based on us wanting to change something.

The first step is installing the plugin, and immediately you get a Products post type you can use to add new products. We’re selling a T-Shirt, so that looks like this:

Note the variations in use for size. We even track inventory at the size level so our T-Shirt printing company knows when to re-print different sizes.

What is somewhat astounding about WooCommerce is that you might need to do very little else. You could set a price, flip on the basic PayPal integration and enter your email, publish the product, and start taking orders.

Or, you could start customizing things and do as much or as little as you want:

  • You could add as many different payment processors as you like. We like using Stripe for credit card processing at CodePen, but also offer PayPal.
  • You could customize the template of every different page involved, or just use the defaults. At CodePen we have very lightly customized templates for the store homepage and product page.
  • You could get very detailed with calculating shipping costs, or use flat rates. We use a flat rate shipping cost at CodePen almost as marketing: same shipping cost anywhere in the world!
  • You could get into integrations, like connecting it with your MailChimp account for further email marketing or Slack account to notify your team of sales.

If you can dream it, you can do it with WooCommerce.

At CodePen, we work with a company called RealThread that actually prints and ships the T-Shirts.

They work great with WooCommerce of course, and the way we set that up is that we use the ShipStation integration and blast the orders into their account there and they handle all the fulfillment from there. There are all sorts of shipping method plugins though for anything you can think of.

Within WooCommerce, we have a dashboard of all the orders, their status, and even tracking information should we need to look something up.

So essentially:

  1. We use WooCommerce
  2. We use the Stripe plugin to take our credit card payments that way
  3. We use the PayPal plugin to take PayPal payments over Braintree
  4. We use the ShipStation plugin to send orders to that system for our fulfillment company to handle

It was quite easy to set up and works great, and it’s comforting to know that we could do tons more with it if we needed to and support is there to help.

The post A Basic WooCommerce Setup to Sell T-Shirts appeared first on CSS-Tricks.

Using feature detection to write CSS with cross-browser support

Post pobrano z: Using feature detection to write CSS with cross-browser support

In early 2017, I presented a couple of workshops on the topic of CSS feature detection, titled CSS Feature Detection in 2017.

A friend of mine, Justin Slack from New Media Labs, recently sent me a link to the phenomenal Feature Query Manager extension (available for both Chrome and Firefox), by Nigerian developer Ire Aderinokun. This seemed to be a perfect addition to my workshop material on the subject.

However, upon returning to the material, I realized how much my work on the subject has aged in the last 18 months.

The CSS landscape has undergone some tectonic shifts:

The above prompted me to not only revisit my existing material, but also ponder the state of CSS feature detection in the upcoming 18 months.

In short:

  1. ❓ Why do we need CSS feature detection at all?
  2. 🛠️ What are good (and not so good) ways to do feature detection?
  3. 🤖 What does the future hold for CSS feature detection?

Cross-browser compatible CSS

When working with CSS, it seems that one of the top concerns always ends up being inconsistent feature support among browsers. This means that CSS styling might look perfect on my browsers of choice, but might be completely broken on another (perhaps an even more popular) browser.

Luckily, dealing with inconsistent browser support is trivial due to a key feature in the design of the CSS language itself. This behavior, called fault tolerance, means that browsers ignore CSS code they don’t understand. This is in stark contrast to languages like JavaScript or PHP that stop all execution in order to throw an error.

The critical implication here is that if we layer our CSS accordingly, properties will only be applied if the browser understands what they mean. As an example, you can include the following CSS rule and the browser will just ignore it— overriding the initial yellow color, but ignoring the third nonsensical value:

background-color: yellow;
background-color: blue; /* Overrides yellow */
background-color: aqy8godf857wqe6igrf7i6dsgkv; /* Ignored */

To illustrate how this can be used in practice, let me start with a contrived, but straightforward situation:

A client comes to you with a strong desire to include a call-to-action (in the form of a popup) on his homepage. With your amazing front-end skills, you are able to quickly produce the most obnoxious pop-up message known to man:

Unfortunately, it turns out that his wife has an old Windows XP machine running Internet Explorer 8. You’re shocked to learn that what she sees no longer resembles a popup in any shape or form.

But! We remember that by using the magic of CSS fault tolerance, we can remedy the situation. We identify all the mission-critical parts of the styling (e.g., the shadow is nice to have, but does not add anything useful usability-wise) and buffer prepend all core styling with fallbacks.

This means that our CSS now looks something like the following (the overrides are highlighted for clarity):

.overlay {
  background: grey;
  background: rgba(0, 0, 0, 0.4);
  border: 1px solid grey;
  border: 1px solid rgba(0, 0, 0, 0.4);
  padding: 64px;
  padding: 4rem;
  display: block;
  display: flex;
  justify-content: center; /* if flex is supported */
  align-items: center; /* if flex is supported */
  height: 100%;
  width: 100%;
}

.popup {
  background: white;
  background-color: rgba(255, 255, 255, 1);
  border-radius: 8px;
  border: 1px solid grey;
  border: 1px solid rgba(0, 0, 0, 0.4);
  box-shadow: 
    0 7px 8px -4px rgba(0,0, 0, 0.2),
    0 13px 19px 2px rgba(0, 0, 0, 0.14),
    0 5px 24px 4px rgba(0, 0, 0, 0.12);
  padding: 32px;
  padding: 2rem;
  min-width: 240px;
}

button {
  background-color: #e0e1e2;
  background-color: rgba(225, 225, 225, 1);
  border-width: 0;
  border-radius: 4px;
  border-radius: 0.25rem;
  box-shadow: 
    0 1px 3px 0 rgba(0,0,0,.2), 
    0 1px 1px 0 rgba(0,0,0,.14), 
    0 2px 1px -1px rgba(0,0,0,.12);
  color: #5c5c5c;
  color: rgba(95, 95, 95, 1);
  cursor: pointer;
  font-weight: bold;
  font-weight: 700;
  padding: 16px;
  padding: 1rem;
}

button:hover {
  background-color: #c8c8c8;
  background-color: rgb(200,200,200); 
}

The above example generally falls under the broader approach of Progressive Enhancement. If you’re interested in learning more about Progressive Enhancement check out Aaron Gustafson’s second edition of his stellar book on the subject, titled Adaptive Web Design: Crafting Rich Experiences with Progressive Enhancement (2016).

If you’re new to front-end development, you might wonder how on earth does one know the support level of specific CSS properties. The short answer is that the more you work with CSS, the more you will learn these by heart. However, there are a couple of tools that are able to help us along the way:

Even with all the above at our disposal, learning CSS support by heart will help us plan our styling up front and increase our efficiency when writing it.

Limits of CSS fault tolerance

The next week, your client returns with a new request. He wants to gather some feedback from users on the earlier changes that were made to the homepage—again, with a pop-up:

Once again it will look as follows in Internet Explorer 8:

Being more proactive this time, you use your new fallback skills to establish a base level of styling that works on Internet Explorer 8 and progressive styling for everything else. Unfortunately, we still run into a problem…

In order to replace the default radio buttons with ASCII hearts, we use the ::before pseudo-element. However this pseudo-element is not supported in Internet Explorer 8. This means that the heart icon does not render; however the display: none property on the <input type="radio"> element still triggers on Internet Explorer 8. The implication being that neither the replacement behavior nor the default behavior is shown.

Credit to John Faulds for pointing out that it is actually possible to get the ’::before’ pseudo-element to work in Internet Explorer 8 if you replace the official double colon syntax with a single colon.

In short, we have a rule (display: none) whose execution should not be bound to its own support (and thus its own fallback structure), but to the support level of a completely separate CSS feature (::before).

For all intents and purposes, the common approach is to explore whether there are more straightforward solutions that do not rely on ::before. However, for the sake of this example, let’s say that the above solution is non-negotiable (and sometimes they are).

Enter User Agent Detection

A solution might be to determine what browser the user is using and then only apply display: none if their browser supports the ::before pseudo-element.

In fact, this approach is almost as old as the web itself. It is known as User Agent Detection or, more colloquially, browser sniffing.

It is usually done as follows:

  • All browsers add a JavaScript property on the global window object called navigator and this object contains a userAgent string property.
  • In my case, the userAgent string is: Mozilla/5.0 (Windows NT10.0;Win64;x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.9 Safari/537.36.
  • Mozilla Developer Network has a comprehensive list of how the above can be used to determine the browser.
  • If we are using Chrome, then the following should return true: (navigator.userAgent.indexOf("chrome") !== -1).
  • However, under the Internet Explorer section on MDN, we just get Internet Explorer. IE doesn’t put its name in the BrowserName/VersionNumber format.
  • Luckily, Internet Explorer provides its own native detection in the form of Conditional Comments.

This means that adding the following in our HTML should suffice:

<!--[if lt IE 9]>
  <style>
    input {
      display: block;
    }
  </style>
<![endif]-->

This means that the above will be applied, should the browser be a version of Internet Explorer lower than version 9 (IE 9 supports ::before)—effectively overriding the display: none property.
Seems straightforward enough?

Unfortunately, over time, some critical flaws emerged in User Agent Detection. So much so that Internet Explorer stopped supporting Conditional Comments from version 10 onward. You will also notice that in the Mozilla Developer Network link itself, the following is presented in an orange alert:

It’s worth re-iterating: it’s very rarely a good idea to use user agent sniffing. You can almost always find a better, more broadly compatible way to solve your problem!

The biggest drawback of User Agent Detection is that browser vendors started spoofing their user agent strings over time due to the following:

  • Developer adds CSS feature that is not supported in the browser.
  • Developer adds User Agent Detection code to serve fallbacks to the browser.
  • Browser eventually adds support for that specific CSS feature.
  • Original User Agent Detection code is not updated to take this into consideration.
  • Code always displays the fallback, even if the browser now supports the CSS feature.
  • Browser uses a fake user agent string to give users the best experience on the web.

Furthermore, even if we were able to infallibly determine every browser type and version, we would have to actively maintain and update our User Agent Detection to reflect the feature support state of those browsers (notwithstanding browsers that have not even been developed yet).

It is important to note that although there are superficial similarities between feature detection and User Agent Detection, feature detection takes a radically different approach than User Agent Detection. According to the Mozilla Developer Network, when we use feature detection, we are essentially doing the following:

  1. 🔎 Testing whether a browser is actually able to run a specific line (or lines) of HTML, CSS or JavaScript code.
  2. 💪 Taking a specific action based on the outcome of this test.

We can also look to Wikipedia for a more formal definition (emphasis mine):

Feature detection (also feature testing) is a technique used in web development for handling differences between runtime environments (typically web browsers or user agents), by programmatically testing for clues that the environment may or may not offer certain functionality. This information is then used to make the application adapt in some way to suit the environment: to make use of certain APIs, or tailor for a better user experience.

While a bit esoteric, this definition does highlight two important aspects of feature detection:

  • Feature detection is a technique, as opposed to a specific tool or technology. This means that there are various (equally valid) ways to accomplish feature detection.
  • Feature detection programmatically tests code. This means that browsers actually run a piece of code to see what happens, as opposed to merely using inference or comparing it against a theoretical reference/list as done with User Agent Detection.

CSS feature detection with @supports

The core concept is not to ask „What browser is this?” It’s to ask „Does your browser support the feature I want to use?”.

—Rob Larson, The Uncertain Web: Web Development in a Changing Landscape (2014)

Most modern browsers support a set of native CSS rules called CSS conditional rules. These allow us to test for certain conditions within the stylesheet itself. The latest iteration (known as module level 3) is described by the Cascading Style Sheets Working Group as follows:

This module contains the features of CSS for conditional processing of parts of style sheets, conditioned on capabilities of the processor or the document the style sheet is being applied to. It includes and extends the functionality of CSS level 2 [CSS21], which builds on CSS level 1 [CSS1]. The main extensions compared to level 2 are allowing nesting of certain at-rules inside ‘@media’, and the addition of the ‘@supports’ rule for conditional processing.

If you’ve used @media, @document or @import before, then you already have experience working with CSS conditional rules. For example when using CSS media queries we do the following:

  • Wrap a single or multiple CSS declarations in a code block with curly brackets, { }.
  • Prepend the code block with a @media query with additional information.
  • Include an optional media type. This can either be all, print, speech or the commonly used screen type.
  • Chain expressions with and/or to determine the scope. For example, if we use (min-width: 300px) and (max-width: 800px), it will trigger the query if the screen size is wider than 300 pixels and smaller than 800 pixels.

The feature queries spec (editor’s draft) prescribes behavior that is conveniently similar to the above example. Instead of using a query expression to set a condition based on the screen size, we write an expression to scope our code block according to a browser’s CSS support (emphasis mine):

The ‘@supports rule allows CSS to be conditioned on implementation support for CSS properties and values. This rule makes it much easier for authors to use new CSS features and provide good fallback for implementations that do not support those features. This is particularly important for CSS features that provide new layout mechanisms, and for other cases where a set of related styles needs to be conditioned on property support.

In short, feature queries are a small built-in CSS tool that allow us to only execute code (like the display: none example above) when a browser supports a separate CSS feature—and much like media queries, we are able to chain expressions as follows: @supports (display: grid) and ((animation-name: spin) or (transition: transform(rotate(360deg)).

So, theoretically, we should be able to do the following:

@supports (::before) {
  input {
    display: none;
  }
}

Unfortunately, it seems that in our example above the display: none property did not trigger, in spite of the fact that your browser probably supports ::before.

That’s because there are some caveats to using @supports:

  • First and foremost, CSS feature queries only support CSS properties and not CSS pseudo-element, like ::before.
  • Secondly, you will see that in the above example our @supports (transform: scale(2)) and (animation-name: beat) condition fires correctly. However if we were to test it in Internet Explorer 11 (which supports both transform: scale(2) and animation-name: beat) it does not fire. What gives? In short, @supports is a CSS feature, with a support matrix of its own.

CSS feature detection with Modernizr

Luckily, the fix is fairly easy! It comes in the form of an open source JavaScript library named Modernizr, initially developed by Faruk Ateş (although it now has some pretty big names behind it, like Paul Irish from Chrome and Alex Sexton from Stripe).

Before we dig into Modernizr, let’s address a subject of great confusion for many developers (partly due to the name „Modernizr” itself). Modernizr does not transform your code or magically enable unsupported features. In fact, the only change Modernzr makes to your code is appending specific CSS classes to your <html> tag.

This means that you might end up with something like the following:

<html class="js flexbox flexboxlegacy canvas canvastext webgl no-touch geolocation postmessage websqldatabase indexeddb hashchange history draganddrop websockets rgba hsla multiplebgs backgroundsize borderimage borderradius boxshadow textshadow opacity cssanimations csscolumns cssgradients cssreflections csstransforms csstransforms3d csstransitions fontface generatedcontent video audio localstorage sessionstorage webworkers applicationcache svg inlinesvg smil svgclippaths">

That is one big HTML tag! However, it allows us do something super powerful: use the CSS descendant selector to conditionally apply CSS rules.

When Modernizr runs, it uses JavaScript to detect what the user’s browser supports, and if it does support that feature, Modernizr injects the name of it as a class to the <html>. Alternatively, if the browser does not support the feature, it prefixes the injected class with no- (e.g., no-generatedcontent in our ::before example). This means that we can write our conditional rule in the stylesheet as follows:

.generatedcontent input {
  display: none
}

In addition, we are able to replicate the chaining of @supports expressions in Modernizr as follows:

/* default */
.generatedcontent input { }

/* 'or' operator */
.generatedcontent input, .csstransforms input { }

/* 'and' operator */
.generatedcontent.csstransformsinput { }

/* 'not' operator */
.no-generatedcontent input { }

Since Modernizr runs in JavaScript (and does not use any native browser APIs), it’s effectively supported on almost all browsers. This means that by leveraging classes like generatedcontent and csstransforms, we are able to cover all our bases for Internet Explorer 8, while still serving bleeding-edge CSS to the latest browsers.

It is important to note that since the release of Modernizr 3.0, we are no longer able to download a stock-standard modernizr.js file with everything except the kitchen sink. Instead, we have to explicitly generate our own custom Modernizr code via their wizard (to copy or download). This is most likely in response to the increasing global focus on web performance over the last couple of years. Checking for more features contributes to more loading, so Modernizr wants us to only check for what we need.

So, I should always use Modernizr?

Given that Modernizr is effectively supported across all browsers, is there any point in even using CSS feature queries? Ironically, I would not only say that we should but that feature queries should still be our first port of call.

First and foremost, the fact that Modernizr does not plug directly into the browser API is it’s greatest strength—it does not rely on the availability of a specific browser API. However, this benefit comes a cost, and that cost is additional overhead to something most browsers support out of the box through @supports—especially when you’re delivering this additional overhead to all users indiscriminately in order to a small amount of edge users. It is important to note that, in our example above, Internet Explorer 8 currently only stands at 0.18% global usage).

Compared to the light touch of @supports, Modernizr has the following drawbacks:

  • The approach underpinning development of Modernizr is driven by the assumption that Modernizr was „meant from day one to eventually become unnecessary.”
  • In the majority of cases, Modernizr needs to be render blocking. This means that Modernizr needs to be downloaded and executed in JavaScript before a web page can even show content on the screen—increasing our page load time (especially on mobile devices)!
  • In order to run tests, Modernizr often has to actually build hidden HTML nodes and test whether it works. For example, in order to test for <canvas> support, Modernizr executes the follow JavaScript code: return !!(document.createElement('canvas').getContext && document.createElement('canvas').getContext('2d'));. This consumes CPU processing power that could be used elsewhere.
  • The CSS descendant selector pattern used by Modernizr increases CSS specificity. (See Harry Roberts’ excellent article on why „specificity is a trait best avoided.”)
  • Although Modernizr covers a lot of tests (150+), it still does not cover the entire spectrum of CSS properties like @support does. The Modernizr team actively maintains a list of these undetectables.

Given that feature queries have already been widely implemented across the browser landscape, (covering about 93.42% of global browsers at the time of writing), it’s been a good while since I’ve used Modernizr. However, it is good to know that it exists as an option should we run into the limitations of @supports or if we need to support users still locked into older browsers or devices for a variety of potential reasons.

Furthermore, when using Modernizr, it is usually in conjunction with @supports as follows:

.generatedcontent input {
  display: none;
}

label:hover::before {
  color: #c6c8c9;
}

input:checked + label::before {
  color: black;
}

@supports (transform: scale(2)) and (animation-name: beat) {
  input:checked + label::before {
    color: #e0e1e2;
    animation-name: beat;
    animation-iteration-count: infinite;
    animation-direction: alternate;
  }
}

This triggers the following to happen:

  • If ::before is not supported, our CSS will fallback to the default HTML radio select.
  • If neither transform(scale(2)) nor animation-name: beat are supported but ::before is, then the heart icon will change to black instead of animate when selected.
  • If transform(scale(2), animation-name: beat and ::before are supported, then the heart icon will animate when selected.

The future of CSS feature detection

Up until this point, I’ve shied away from talking about feature detection in a world being eaten by JavaScript, or possibly even a post-JavaScript world. Perhaps even intentionally so, since current iterations at the intersection between CSS and JavaScript are extremely contentious and divisive.

From that moment on, the web community was split in two by an intense debate between those who see CSS as an untouchable layer in the „separation of concerns” paradigm (content + presentation + behaviour, HTML + CSS + JS) and those who have simply ignored this golden rule and found different ways to style the UI, typically applying CSS styles via JavaScript. This debate has become more and more intense every day, bringing division in a community that used to be immune to this kind of „religion wars”.

—Cristiano Rastelli, Let there be peace on CSS (2017)

However, I think exploring how to apply feature detection in the modern CSS-in-JS toolchain might be of value as follows:

  • It provides an opportunity to explore how CSS feature detection would work in a radically different environment.
  • It showcases feature detection as a technique, as opposed to a specific technology or tool.

With this in mind, let us start by examining an implementation of our pop-up by means of the most widely-used CSS-in-JS library (at least at the time of writing), Styled Components:

This is how it will look in Internet Explorer 8:

In our previous examples, we’ve been able to conditionally execute CSS rules based on the browser support of ::before (via Modernizr) and transform (via @supports). However, by leveraging JavaScript, we are able to take this even further. Since both @supports and Modernizr expose their APIs via JavaScript, we are able to conditionally load entire parts of our pop-up based solely on browser support.

Keep in mind that you will probably need to do a lot of heavy lifting to get React and Styled Components working in a browser that does not even support ::before (checking for display: grid might make more sense in this context), but for the sake of keeping with the above examples, let us assume that we have React and Styled Components running in Internet Explorer 8 or lower.

In the example above, you will notice that we’ve created a component, called ValueSelection. This component returns a clickable button that increments the amount of likes on click. If you are viewing the example on a slightly older browser, you might notice that instead of the button you will see a dropdown with values from 0 to 9.

In order to achieve this, we’re conditionally returning an enhanced version of the component only if the following conditions are met:

if (
  CSS.supports('transform: scale(2)') &&
  CSS.supports('animation-name: beat') &&
  Modernizr.generatedcontent
) {
  return (
    <React.Fragment>
      <Modern type="button" onClick={add}>{string}</Modern> 
      <input type="hidden" name="liked" value={value} />
    </React.Fragment>
  )
}

return (
  <Base value={value} onChange={select}>
    {
      [1,2,3,4,5,6,7,8,9].map(val => (
        <option value={val} key={val}>{val}</option>
      ))
    }
  </Base>
);

What is intriguing about this approach is that the ValueSelection component only exposes two parameters:

  • The current amount of likes
  • The function to run when the amount of likes are updated
<Overlay>
  <Popup>
    <Title>How much do you like popups?</Title>
    <form>
      <ValueInterface value={liked} change={changeLike} />
      <Button type="submit">Submit</Button>
    </form>
  </Popup>
</Overlay>

In other words, the component’s logic is completely separate from its presentation. The component itself will internally decide what presentation works best given a browser’s support matrix. Having the conditional presentation abstracted away inside the component itself opens the door to exciting new ways of building cross-browser compatible interfaces when working in a front-end and/or design team.

Here’s the final product:

…and how it should theoretically look in Internet Explorer 8:

Additional Resources

If you are interested in diving deeper into the above you can visit the following resources:


Schalk is a South African front-end developer/designer passionate about the role technology and the web can play as a force for good in his home country. He works full time with a group of civic tech minded developers at a South African non-profit called OpenUp.

He also helps manage a collaborative space called Codebridge where developers are encouraged to come and experiment with technology as a tool to bridge social divides and solve problems alongside local communities.

The post Using feature detection to write CSS with cross-browser support appeared first on CSS-Tricks.

Using feature detection to write CSS with cross-browser support

Post pobrano z: Using feature detection to write CSS with cross-browser support

In early 2017, I presented a couple of workshops on the topic of CSS feature detection, titled CSS Feature Detection in 2017.

A friend of mine, Justin Slack from New Media Labs, recently sent me a link to the phenomenal Feature Query Manager extension (available for both Chrome and Firefox), by Nigerian developer Ire Aderinokun. This seemed to be a perfect addition to my workshop material on the subject.

However, upon returning to the material, I realized how much my work on the subject has aged in the last 18 months.

The CSS landscape has undergone some tectonic shifts:

The above prompted me to not only revisit my existing material, but also ponder the state of CSS feature detection in the upcoming 18 months.

In short:

  1. ❓ Why do we need CSS feature detection at all?
  2. 🛠️ What are good (and not so good) ways to do feature detection?
  3. 🤖 What does the future hold for CSS feature detection?

Cross-browser compatible CSS

When working with CSS, it seems that one of the top concerns always ends up being inconsistent feature support among browsers. This means that CSS styling might look perfect on my browsers of choice, but might be completely broken on another (perhaps an even more popular) browser.

Luckily, dealing with inconsistent browser support is trivial due to a key feature in the design of the CSS language itself. This behavior, called fault tolerance, means that browsers ignore CSS code they don’t understand. This is in stark contrast to languages like JavaScript or PHP that stop all execution in order to throw an error.

The critical implication here is that if we layer our CSS accordingly, properties will only be applied if the browser understands what they mean. As an example, you can include the following CSS rule and the browser will just ignore it— overriding the initial yellow color, but ignoring the third nonsensical value:

background-color: yellow;
background-color: blue; /* Overrides yellow */
background-color: aqy8godf857wqe6igrf7i6dsgkv; /* Ignored */

To illustrate how this can be used in practice, let me start with a contrived, but straightforward situation:

A client comes to you with a strong desire to include a call-to-action (in the form of a popup) on his homepage. With your amazing front-end skills, you are able to quickly produce the most obnoxious pop-up message known to man:

Unfortunately, it turns out that his wife has an old Windows XP machine running Internet Explorer 8. You’re shocked to learn that what she sees no longer resembles a popup in any shape or form.

But! We remember that by using the magic of CSS fault tolerance, we can remedy the situation. We identify all the mission-critical parts of the styling (e.g., the shadow is nice to have, but does not add anything useful usability-wise) and buffer prepend all core styling with fallbacks.

This means that our CSS now looks something like the following (the overrides are highlighted for clarity):

.overlay {
  background: grey;
  background: rgba(0, 0, 0, 0.4);
  border: 1px solid grey;
  border: 1px solid rgba(0, 0, 0, 0.4);
  padding: 64px;
  padding: 4rem;
  display: block;
  display: flex;
  justify-content: center; /* if flex is supported */
  align-items: center; /* if flex is supported */
  height: 100%;
  width: 100%;
}

.popup {
  background: white;
  background-color: rgba(255, 255, 255, 1);
  border-radius: 8px;
  border: 1px solid grey;
  border: 1px solid rgba(0, 0, 0, 0.4);
  box-shadow: 
    0 7px 8px -4px rgba(0,0, 0, 0.2),
    0 13px 19px 2px rgba(0, 0, 0, 0.14),
    0 5px 24px 4px rgba(0, 0, 0, 0.12);
  padding: 32px;
  padding: 2rem;
  min-width: 240px;
}

button {
  background-color: #e0e1e2;
  background-color: rgba(225, 225, 225, 1);
  border-width: 0;
  border-radius: 4px;
  border-radius: 0.25rem;
  box-shadow: 
    0 1px 3px 0 rgba(0,0,0,.2), 
    0 1px 1px 0 rgba(0,0,0,.14), 
    0 2px 1px -1px rgba(0,0,0,.12);
  color: #5c5c5c;
  color: rgba(95, 95, 95, 1);
  cursor: pointer;
  font-weight: bold;
  font-weight: 700;
  padding: 16px;
  padding: 1rem;
}

button:hover {
  background-color: #c8c8c8;
  background-color: rgb(200,200,200); 
}

The above example generally falls under the broader approach of Progressive Enhancement. If you’re interested in learning more about Progressive Enhancement check out Aaron Gustafson’s second edition of his stellar book on the subject, titled Adaptive Web Design: Crafting Rich Experiences with Progressive Enhancement (2016).

If you’re new to front-end development, you might wonder how on earth does one know the support level of specific CSS properties. The short answer is that the more you work with CSS, the more you will learn these by heart. However, there are a couple of tools that are able to help us along the way:

Even with all the above at our disposal, learning CSS support by heart will help us plan our styling up front and increase our efficiency when writing it.

Limits of CSS fault tolerance

The next week, your client returns with a new request. He wants to gather some feedback from users on the earlier changes that were made to the homepage—again, with a pop-up:

Once again it will look as follows in Internet Explorer 8:

Being more proactive this time, you use your new fallback skills to establish a base level of styling that works on Internet Explorer 8 and progressive styling for everything else. Unfortunately, we still run into a problem…

In order to replace the default radio buttons with ASCII hearts, we use the ::before pseudo-element. However this pseudo-element is not supported in Internet Explorer 8. This means that the heart icon does not render; however the display: none property on the <input type="radio"> element still triggers on Internet Explorer 8. The implication being that neither the replacement behavior nor the default behavior is shown.

Credit to John Faulds for pointing out that it is actually possible to get the ’::before’ pseudo-element to work in Internet Explorer 8 if you replace the official double colon syntax with a single colon.

In short, we have a rule (display: none) whose execution should not be bound to its own support (and thus its own fallback structure), but to the support level of a completely separate CSS feature (::before).

For all intents and purposes, the common approach is to explore whether there are more straightforward solutions that do not rely on ::before. However, for the sake of this example, let’s say that the above solution is non-negotiable (and sometimes they are).

Enter User Agent Detection

A solution might be to determine what browser the user is using and then only apply display: none if their browser supports the ::before pseudo-element.

In fact, this approach is almost as old as the web itself. It is known as User Agent Detection or, more colloquially, browser sniffing.

It is usually done as follows:

  • All browsers add a JavaScript property on the global window object called navigator and this object contains a userAgent string property.
  • In my case, the userAgent string is: Mozilla/5.0 (Windows NT10.0;Win64;x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.9 Safari/537.36.
  • Mozilla Developer Network has a comprehensive list of how the above can be used to determine the browser.
  • If we are using Chrome, then the following should return true: (navigator.userAgent.indexOf("chrome") !== -1).
  • However, under the Internet Explorer section on MDN, we just get Internet Explorer. IE doesn’t put its name in the BrowserName/VersionNumber format.
  • Luckily, Internet Explorer provides its own native detection in the form of Conditional Comments.

This means that adding the following in our HTML should suffice:

<!--[if lt IE 9]>
  <style>
    input {
      display: block;
    }
  </style>
<![endif]-->

This means that the above will be applied, should the browser be a version of Internet Explorer lower than version 9 (IE 9 supports ::before)—effectively overriding the display: none property.
Seems straightforward enough?

Unfortunately, over time, some critical flaws emerged in User Agent Detection. So much so that Internet Explorer stopped supporting Conditional Comments from version 10 onward. You will also notice that in the Mozilla Developer Network link itself, the following is presented in an orange alert:

It’s worth re-iterating: it’s very rarely a good idea to use user agent sniffing. You can almost always find a better, more broadly compatible way to solve your problem!

The biggest drawback of User Agent Detection is that browser vendors started spoofing their user agent strings over time due to the following:

  • Developer adds CSS feature that is not supported in the browser.
  • Developer adds User Agent Detection code to serve fallbacks to the browser.
  • Browser eventually adds support for that specific CSS feature.
  • Original User Agent Detection code is not updated to take this into consideration.
  • Code always displays the fallback, even if the browser now supports the CSS feature.
  • Browser uses a fake user agent string to give users the best experience on the web.

Furthermore, even if we were able to infallibly determine every browser type and version, we would have to actively maintain and update our User Agent Detection to reflect the feature support state of those browsers (notwithstanding browsers that have not even been developed yet).

It is important to note that although there are superficial similarities between feature detection and User Agent Detection, feature detection takes a radically different approach than User Agent Detection. According to the Mozilla Developer Network, when we use feature detection, we are essentially doing the following:

  1. 🔎 Testing whether a browser is actually able to run a specific line (or lines) of HTML, CSS or JavaScript code.
  2. 💪 Taking a specific action based on the outcome of this test.

We can also look to Wikipedia for a more formal definition (emphasis mine):

Feature detection (also feature testing) is a technique used in web development for handling differences between runtime environments (typically web browsers or user agents), by programmatically testing for clues that the environment may or may not offer certain functionality. This information is then used to make the application adapt in some way to suit the environment: to make use of certain APIs, or tailor for a better user experience.

While a bit esoteric, this definition does highlight two important aspects of feature detection:

  • Feature detection is a technique, as opposed to a specific tool or technology. This means that there are various (equally valid) ways to accomplish feature detection.
  • Feature detection programmatically tests code. This means that browsers actually run a piece of code to see what happens, as opposed to merely using inference or comparing it against a theoretical reference/list as done with User Agent Detection.

CSS feature detection with @supports

The core concept is not to ask „What browser is this?” It’s to ask „Does your browser support the feature I want to use?”.

—Rob Larson, The Uncertain Web: Web Development in a Changing Landscape (2014)

Most modern browsers support a set of native CSS rules called CSS conditional rules. These allow us to test for certain conditions within the stylesheet itself. The latest iteration (known as module level 3) is described by the Cascading Style Sheets Working Group as follows:

This module contains the features of CSS for conditional processing of parts of style sheets, conditioned on capabilities of the processor or the document the style sheet is being applied to. It includes and extends the functionality of CSS level 2 [CSS21], which builds on CSS level 1 [CSS1]. The main extensions compared to level 2 are allowing nesting of certain at-rules inside ‘@media’, and the addition of the ‘@supports’ rule for conditional processing.

If you’ve used @media, @document or @import before, then you already have experience working with CSS conditional rules. For example when using CSS media queries we do the following:

  • Wrap a single or multiple CSS declarations in a code block with curly brackets, { }.
  • Prepend the code block with a @media query with additional information.
  • Include an optional media type. This can either be all, print, speech or the commonly used screen type.
  • Chain expressions with and/or to determine the scope. For example, if we use (min-width: 300px) and (max-width: 800px), it will trigger the query if the screen size is wider than 300 pixels and smaller than 800 pixels.

The feature queries spec (editor’s draft) prescribes behavior that is conveniently similar to the above example. Instead of using a query expression to set a condition based on the screen size, we write an expression to scope our code block according to a browser’s CSS support (emphasis mine):

The ‘@supports rule allows CSS to be conditioned on implementation support for CSS properties and values. This rule makes it much easier for authors to use new CSS features and provide good fallback for implementations that do not support those features. This is particularly important for CSS features that provide new layout mechanisms, and for other cases where a set of related styles needs to be conditioned on property support.

In short, feature queries are a small built-in CSS tool that allow us to only execute code (like the display: none example above) when a browser supports a separate CSS feature—and much like media queries, we are able to chain expressions as follows: @supports (display: grid) and ((animation-name: spin) or (transition: transform(rotate(360deg)).

So, theoretically, we should be able to do the following:

@supports (::before) {
  input {
    display: none;
  }
}

Unfortunately, it seems that in our example above the display: none property did not trigger, in spite of the fact that your browser probably supports ::before.

That’s because there are some caveats to using @supports:

  • First and foremost, CSS feature queries only support CSS properties and not CSS pseudo-element, like ::before.
  • Secondly, you will see that in the above example our @supports (transform: scale(2)) and (animation-name: beat) condition fires correctly. However if we were to test it in Internet Explorer 11 (which supports both transform: scale(2) and animation-name: beat) it does not fire. What gives? In short, @supports is a CSS feature, with a support matrix of its own.

CSS feature detection with Modernizr

Luckily, the fix is fairly easy! It comes in the form of an open source JavaScript library named Modernizr, initially developed by Faruk Ateş (although it now has some pretty big names behind it, like Paul Irish from Chrome and Alex Sexton from Stripe).

Before we dig into Modernizr, let’s address a subject of great confusion for many developers (partly due to the name „Modernizr” itself). Modernizr does not transform your code or magically enable unsupported features. In fact, the only change Modernzr makes to your code is appending specific CSS classes to your <html> tag.

This means that you might end up with something like the following:

<html class="js flexbox flexboxlegacy canvas canvastext webgl no-touch geolocation postmessage websqldatabase indexeddb hashchange history draganddrop websockets rgba hsla multiplebgs backgroundsize borderimage borderradius boxshadow textshadow opacity cssanimations csscolumns cssgradients cssreflections csstransforms csstransforms3d csstransitions fontface generatedcontent video audio localstorage sessionstorage webworkers applicationcache svg inlinesvg smil svgclippaths">

That is one big HTML tag! However, it allows us do something super powerful: use the CSS descendant selector to conditionally apply CSS rules.

When Modernizr runs, it uses JavaScript to detect what the user’s browser supports, and if it does support that feature, Modernizr injects the name of it as a class to the <html>. Alternatively, if the browser does not support the feature, it prefixes the injected class with no- (e.g., no-generatedcontent in our ::before example). This means that we can write our conditional rule in the stylesheet as follows:

.generatedcontent input {
  display: none
}

In addition, we are able to replicate the chaining of @supports expressions in Modernizr as follows:

/* default */
.generatedcontent input { }

/* 'or' operator */
.generatedcontent input, .csstransforms input { }

/* 'and' operator */
.generatedcontent.csstransformsinput { }

/* 'not' operator */
.no-generatedcontent input { }

Since Modernizr runs in JavaScript (and does not use any native browser APIs), it’s effectively supported on almost all browsers. This means that by leveraging classes like generatedcontent and csstransforms, we are able to cover all our bases for Internet Explorer 8, while still serving bleeding-edge CSS to the latest browsers.

It is important to note that since the release of Modernizr 3.0, we are no longer able to download a stock-standard modernizr.js file with everything except the kitchen sink. Instead, we have to explicitly generate our own custom Modernizr code via their wizard (to copy or download). This is most likely in response to the increasing global focus on web performance over the last couple of years. Checking for more features contributes to more loading, so Modernizr wants us to only check for what we need.

So, I should always use Modernizr?

Given that Modernizr is effectively supported across all browsers, is there any point in even using CSS feature queries? Ironically, I would not only say that we should but that feature queries should still be our first port of call.

First and foremost, the fact that Modernizr does not plug directly into the browser API is it’s greatest strength—it does not rely on the availability of a specific browser API. However, this benefit comes a cost, and that cost is additional overhead to something most browsers support out of the box through @supports—especially when you’re delivering this additional overhead to all users indiscriminately in order to a small amount of edge users. It is important to note that, in our example above, Internet Explorer 8 currently only stands at 0.18% global usage).

Compared to the light touch of @supports, Modernizr has the following drawbacks:

  • The approach underpinning development of Modernizr is driven by the assumption that Modernizr was „meant from day one to eventually become unnecessary.”
  • In the majority of cases, Modernizr needs to be render blocking. This means that Modernizr needs to be downloaded and executed in JavaScript before a web page can even show content on the screen—increasing our page load time (especially on mobile devices)!
  • In order to run tests, Modernizr often has to actually build hidden HTML nodes and test whether it works. For example, in order to test for <canvas> support, Modernizr executes the follow JavaScript code: return !!(document.createElement('canvas').getContext && document.createElement('canvas').getContext('2d'));. This consumes CPU processing power that could be used elsewhere.
  • The CSS descendant selector pattern used by Modernizr increases CSS specificity. (See Harry Roberts’ excellent article on why „specificity is a trait best avoided.”)
  • Although Modernizr covers a lot of tests (150+), it still does not cover the entire spectrum of CSS properties like @support does. The Modernizr team actively maintains a list of these undetectables.

Given that feature queries have already been widely implemented across the browser landscape, (covering about 93.42% of global browsers at the time of writing), it’s been a good while since I’ve used Modernizr. However, it is good to know that it exists as an option should we run into the limitations of @supports or if we need to support users still locked into older browsers or devices for a variety of potential reasons.

Furthermore, when using Modernizr, it is usually in conjunction with @supports as follows:

.generatedcontent input {
  display: none;
}

label:hover::before {
  color: #c6c8c9;
}

input:checked + label::before {
  color: black;
}

@supports (transform: scale(2)) and (animation-name: beat) {
  input:checked + label::before {
    color: #e0e1e2;
    animation-name: beat;
    animation-iteration-count: infinite;
    animation-direction: alternate;
  }
}

This triggers the following to happen:

  • If ::before is not supported, our CSS will fallback to the default HTML radio select.
  • If neither transform(scale(2)) nor animation-name: beat are supported but ::before is, then the heart icon will change to black instead of animate when selected.
  • If transform(scale(2), animation-name: beat and ::before are supported, then the heart icon will animate when selected.

The future of CSS feature detection

Up until this point, I’ve shied away from talking about feature detection in a world being eaten by JavaScript, or possibly even a post-JavaScript world. Perhaps even intentionally so, since current iterations at the intersection between CSS and JavaScript are extremely contentious and divisive.

From that moment on, the web community was split in two by an intense debate between those who see CSS as an untouchable layer in the „separation of concerns” paradigm (content + presentation + behaviour, HTML + CSS + JS) and those who have simply ignored this golden rule and found different ways to style the UI, typically applying CSS styles via JavaScript. This debate has become more and more intense every day, bringing division in a community that used to be immune to this kind of „religion wars”.

—Cristiano Rastelli, Let there be peace on CSS (2017)

However, I think exploring how to apply feature detection in the modern CSS-in-JS toolchain might be of value as follows:

  • It provides an opportunity to explore how CSS feature detection would work in a radically different environment.
  • It showcases feature detection as a technique, as opposed to a specific technology or tool.

With this in mind, let us start by examining an implementation of our pop-up by means of the most widely-used CSS-in-JS library (at least at the time of writing), Styled Components:

This is how it will look in Internet Explorer 8:

In our previous examples, we’ve been able to conditionally execute CSS rules based on the browser support of ::before (via Modernizr) and transform (via @supports). However, by leveraging JavaScript, we are able to take this even further. Since both @supports and Modernizr expose their APIs via JavaScript, we are able to conditionally load entire parts of our pop-up based solely on browser support.

Keep in mind that you will probably need to do a lot of heavy lifting to get React and Styled Components working in a browser that does not even support ::before (checking for display: grid might make more sense in this context), but for the sake of keeping with the above examples, let us assume that we have React and Styled Components running in Internet Explorer 8 or lower.

In the example above, you will notice that we’ve created a component, called ValueSelection. This component returns a clickable button that increments the amount of likes on click. If you are viewing the example on a slightly older browser, you might notice that instead of the button you will see a dropdown with values from 0 to 9.

In order to achieve this, we’re conditionally returning an enhanced version of the component only if the following conditions are met:

if (
  CSS.supports('transform: scale(2)') &&
  CSS.supports('animation-name: beat') &&
  Modernizr.generatedcontent
) {
  return (
    <React.Fragment>
      <Modern type="button" onClick={add}>{string}</Modern> 
      <input type="hidden" name="liked" value={value} />
    </React.Fragment>
  )
}

return (
  <Base value={value} onChange={select}>
    {
      [1,2,3,4,5,6,7,8,9].map(val => (
        <option value={val} key={val}>{val}</option>
      ))
    }
  </Base>
);

What is intriguing about this approach is that the ValueSelection component only exposes two parameters:

  • The current amount of likes
  • The function to run when the amount of likes are updated
<Overlay>
  <Popup>
    <Title>How much do you like popups?</Title>
    <form>
      <ValueInterface value={liked} change={changeLike} />
      <Button type="submit">Submit</Button>
    </form>
  </Popup>
</Overlay>

In other words, the component’s logic is completely separate from its presentation. The component itself will internally decide what presentation works best given a browser’s support matrix. Having the conditional presentation abstracted away inside the component itself opens the door to exciting new ways of building cross-browser compatible interfaces when working in a front-end and/or design team.

Here’s the final product:

…and how it should theoretically look in Internet Explorer 8:

Additional Resources

If you are interested in diving deeper into the above you can visit the following resources:


Schalk is a South African front-end developer/designer passionate about the role technology and the web can play as a force for good in his home country. He works full time with a group of civic tech minded developers at a South African non-profit called OpenUp.

He also helps manage a collaborative space called Codebridge where developers are encouraged to come and experiment with technology as a tool to bridge social divides and solve problems alongside local communities.

The post Using feature detection to write CSS with cross-browser support appeared first on CSS-Tricks.

How to Create a Punk-Rock Portrait in Procreate

Post pobrano z: How to Create a Punk-Rock Portrait in Procreate

Final product image
What You’ll Be Creating

This tutorial will introduce you to the basics of Procreate, which can be a great professional tool for you as it is for me. Procreate has quickly become my go-to digital painting app, and I do most of my work in this app. 

In this tutorial, I’ll be using an iPad Pro with the Apple Pencil and Procreate 4. I’ll also guide you through my painting techniques and the process of developing a masculine portrait.

Let’s start!

1. How to Make a Sketch

Step 1

First, open the Procreate application. Tap the (+) icon
in the top right corner to create a New Canvas. Tap to Create
Custom Size 
and create a 3500 x 4000 px canvas size, RGB300 DPI resolution. 

create a new canvas

Step 2

I start the process by gathering the reference materials for my masculine punk character, collecting images with some attributes
inherent to this style.

I create my sketch directly in Procreate using my Apple Pencil. Procreate has a great selection of
sketching brushes, which you can find in the Sketching set.
Any brush from this set will be
suitable for sketching. My favorite is the 6B Pencil brush.

Let’s modify
this brush a little bit to get more flexibility in the sketching process. Tap the 6B
Pencil 
icon, and the Settings of the tool will
appear. Choose the General settings and change the Size
Limits
 to ~30% Max.

pick the sketch tool

Step 3

We already have two layers by default: one layer with the
background color and one empty layer. It’s best
to start with a simple white canvas, without any gradients or colours, so we’re keeping the background color white.

Open the Layers panel, tap „Layer 2”,
and rename it „sketch”. Choose any color you like from the Color menu in the top right
corner.

rename a new layer

Step 4

The references are collected and the brush and color are selected, so now it’s time to create the sketch!

Start with the
basic shapes, keeping the image simple and not going into too much detail. Then
build up your rough sketch into something more refined, adding more details to give them a bit more character.

You can
rotate the canvas in the process for convenience. Just use two fingers and rotate your
image or size it.

Also, you can change the Size and Opacity of
any Brush tool by moving the
sliders on the left side of the screen up and down.

create a sketch

2. How to Create the Line Art

Step 1

First, open the Layers menu, tap N on
the „sketch” layer, and lower the Opacity to about 30%.

make the sketch semitransparent

Then
create a New Layer for your line art on
top of the „sketch” layer.

create a new layer for the lines

Step 2

Let’s create
New Ink Brush for our line work.

First, choose the Inking set, and tap the + icon
in the top-right corner of the brush list to create your New Brush.
The menu with sources will appear.

For the Shape, tap Swap from Pro Library and
choose Ink 2. For
the Grain, tap Swap from Pro Library and choose
the Recycled Paper texture.

create a new ink brush

pick sources for the brush

Rename it „New ink brush”, and use the brush settings shown below.

use the new brush settings

apply the new brush settings

Step 3

Let’s make a few trial lines with our new brush,
so we can sense the lines. The
thickness of the line depends on how hard you press with the pencil.

Then tap on the „lines” layer and select Clear from the drop-down list to delete your trial
lines. Now we can start our line art on the clean layer.

make a trial lines

Step 4

We’re ready to start creating our line art.

First, let’s pick the color for the lines. Choose a deep blue-gray
color from the Colors menu, avoiding black for
a softer look.

pick the color for the line art

The most convenient
method during the work process is to mirror
your image. It will
allow you to control the proportions and have more flexibility in the drawing process. Also, it helps you to take a fresh look at your work, so you can correct any early mistakes.

Just go to Actions > Canvas >
Flip canvas horizontally
as shown below.

mirror the image

Step 5

Set the brush Size to
about 5-10% with 100% Opacity.

Start by
drawing the face with smooth lines on top of your sketch. Create
a variance of line weight, making transitions from thin to thick and imitating
traditional ink. It will give more life to your drawing.

If you feel
the lines are thicker or thinner than you would like them, you can always change their Weight by moving the Brush Size slider on the left side of the
screen up or down.

draw lines of the face

Step 6

Now let’s draw the outfit: jacket,
t-shirt, and rock collar.

Don’t think
about any details on this stage—just draw the main objects of your character’s outfit.

draw lines of the jacket

Let’s add
some necessary details to the outfit.

Draw one rivet on the jacket’s
collar first. Take the Selection tool, and
make sure it’s on Freehand. Select
the area of the rivet. Then tap Transform, which is next in the top panel. Swipe down with three fingers, and the menu
will appear. Choose Copy + Paste and you’ll
get this rivet on a new layer. Move it down
and place it on another part
of the collar.

duplicate objects

Create more rivets using the same principle.

As a result,
we’ll get them as
inserted images on the new layers.
Merge these layers into one. Just tap on the top layer and choose Merge
Down
 from the drop-down list. Or you can take the two layers (one
finger on one, and one finger on the other) and squeeze them together.

merge layers into one

Finish the decoration of the jacket by adding more rivets, buttons, pins, and badges.

finish the jackets outlines

Step 7

I noticed
that the rock collar is too low on the neck. But we can fix it easily.

Tap
the Selection tool, and draw a shape on the area of the collar. Then tap Transform, so you can move this object up a
little. Use the Eraser
to clean the rock collar a little bit, and finish this by drawing some missing
lines.

use the Selection tool

use the Transform tool

In the end, decorate the t-shirt
with a skull drawing.

draw the skull line art

Step 8

Now let’s draw the hairstyle. Create the solid shapes first, making just the main lines. Then add some details
made of very thin lines.

draw the hairs

At once, use the same brush to add some volume and deep contrast shadows to the
hairstyle.

add some volume to the line art

Make the
“sketch” layer invisible and admire the result of the line art.

finish the line art

3. How to Create the Main Shapes

Step 1

Let’s start by filling the background with some basic color.

Pick the Charcoal Block brush from the Charcoals set, and modify it by
changing the Size Limit to about 160%.

brush settings

Now create a New Layer under
the „lines” layer.

Choose pink, and draw the main shape of the background pattern following
the sketch. We can change this
color as necessary later.

draw the background shape

Step 2

We can keep all the
colors that we will pick up in the process by creating a Palette of basic colors.

We have the Colors menu in the top right
corner, where we can select the color.

Click on the + icon to Create a New
Palette
, and a new area with empty boxes for our new palette will appear.
Rename it „Punk-rock”.

Let’s add the pink
from the background first.
Pick the color and tap on any of the empty boxes, and it saves it.

Further
fill these boxes with selected colors to create your own palette.

create the color palette

Step 3

Create
New Layer and
pick a beige color for the skin tone.

Now let’s
find a suitable brush for the
painting. My favorite is the Soft Pastel brush from the Sketching set.

choose the brush for the basic colors

brush settings

Use the Max Size of the brush and fill the
face and neck with color. Clean the area around the body using the Eraser
Tool
. Choose the Soft Pastel brush as an
eraser as well.

Add
this skin tone color to your Palette.

draw the main shape of the face

Step 4

Now let’s find
another cool brush for the jacket.

Go to Brushes > Painting > Nikko Rull,
and change the Size Limit to about 470%.

apply new brush settings

Set the brush Size to
about 70% with 100% Opacity. Pick a dark
violet color and draw large strokes to cover the whole area of the jacket shape. Add this color to your Palette.

draw the main shape of the jacket

Now we need
to clean the area outside of the lines. We
can use the Eraser Tool, as we did before. But in this case I find
the Selection Tool is a more convenient method.

Tap the Selection Tool
and draw a
shape on the area you need to delete. Then tap Transform, swipe
down with three fingers, and the menu will appear. Choose Cut, and
you’ll get an absolutely clean area.

delete the necessary shapes

In
the end, refine the edges using the Eraser
Tool
.

finish the jacket

Step 5

Create new layers for each
group of objects, and fill them with colors using the Soft
Pastel 
brush.

Organize the layers as shown in the screenshot below.

organize layers

Step 6

Let’s set the background color by tapping the
„Background color” layer, which we already have by default. Select a
dark blue color on the Color menu.

change the background color

Now
we need to change the color of our background shape and make it more saturated. It allows us to create a good range of
contrast and make the character more expressive.

First select the layer, and then tap the Adjustments icon
and choose Hue, Saturation, Brightness from
the drop-down list. Move the sliders
until you get the desired result. 

change the backgrounds shape color

4. How to Add Shadows and Highlights

Step 1

Let’s start by adding some volume to the face.

Tap on the „skin” layer and
select Alpha Lock from the drop-down list. It will help us to
paint inside the body shape without crossing this area.

lock in the layer

Now select a peach color and choose the Soft Pastel brush from the Sketching set. I like using
this brush because of the softness and texture, and it also makes the painting look
more realistic.

Start
building the basic shapes of the face and neck with very large
brush strokes and defining the character’s facial features.

Then
create some subtle shadows using a light brown color to show the volume more clearly. You can vary the
brush Size in the process as you like.

draw the subtle shadows on the face

Step 2

This way, add some basic
shadows by making strokes on the shadowy area. Use the Bordeaux color for them.

Then
add a little contrast to the face.
Choose the dark blue-grey color and add some deeper shadows to the eyes, nose, ear, neck, and hair growth line.

draw the shadows on the face

Step 3

Create a New Layer for the highlights on top of the „skin”
layer.

Select a lighter cold tint starting from the base skin color, and paint some
highlight strokes using the same Soft Pastel brush. Reduce the Opacity of the layer to about 65%.

draw the highlights on the face

Once we’re happy with the highlights, we can
merge these layers with highlights and skin into one „skin”
layer. Tap on the top layer with highlights and choose Merge Down from
the drop-down list.

merge skin layers

Let’s refine the skin a little bit,
correcting the roughness of the skin and improving the shape of his face
and neck. Also add some volume to the eyes and lips.

Use the Color Picker Button to
select the color you need. You can find this button between the Size and Opacity sliders. 

refine the skin

Step 4

Once we’re happy with the volume of the face, let’s add some colors to make the skin more natural and bring some life to it.

Create a New Layer on top of the
„skin”, and rename it „color
zone”.

First select the
„skin” layer. Just tap on the layer and choose Select from
the drop-down list. It will allow us to draw on the „color zone” layer just inside the body
shape.

Now we need to add
some variation in color to the face: yellow tones to the forehead and neck,
reddish tones to the cheeks, nose and ear, and blue tones underneath the eyes
and around the chin.

use the color zone

Change the Blending Mode of
this layer to Multiply. Reduce the Opacity to about 20%. You can play around
with the Opacity until you’re happy with how it looks.

apply the color zone

Step 5

Create a New Layer for the bristle on top of the „color zone” layer.

Keeping
the „skin” layer selected, draw large brush strokes on the head and
chin. Use the same Soft
Pastel
brush and a deep
blue color. Refine the edges using the Eraser Tool.

In
the end, change the Blending Mode to Hard Light to add saturated colors and
darken areas simultaneously.

draw the bristle

Step 6

Let’s add some freckles to make the skin more natural.

Create a New Layer on top of
the „skin”, and rename it „freckles”. Choose the Flicks brush from the Spraypaints set and
pick the Bordeaux color. 

brush settings

Apply Select to the
„skin” layer. Using the middle size of the brush, draw some strokes, spraying tiny
spots on the skin area. Change the Blending Mode to Color Burn and reduce
the Opacity to about 20%.

add freckles to the skin

Using the same color and the Soft Pastel brush, add some freckles and moles randomly to the nose, cheeks, and neck.
Vary the brush Size around 5–15% in the
process.  

draw freckles and moles

In the end, let’s draw some falling shadows
from the hair.

Create a New Layer for them on
top of the „skin”. Add some dark blue shadows
to the forehead under the fringe and to the face under the beard.  

draw falling shadows on the head

5. How to Create a Vibrant Hairstyle

Step 1

Let’s start forming the hairstyle.

First, lock the „hair” layer by activating Alpha
Lock
.

lock in the layer

Use the Soft Pastel brush to add some large green and pink shapes to the hairstyle.

draw main shapes of the hair

Draw some deep blue strokes on the roots of the hair and on the
shadowy area of the locks.

Then
use a very saturated green colour and mix it with the pink and blue, creating
some interesting effects.

We
don’t paint every strand individually at this stage, but cluster and form
groups.

form groups of the hairs

Now
eye-drop the colors from the skin to the very roots of the hair, and make some smooth color transitions from the skin to the hair.

Then
create some volume by adding some saturated blue color.

create volume of the hairstyle

Step 2

Use the same Soft Pastel brush and yellow color to add some bright spots to the green part
of the hairstyle. Then draw some gentle aquamarine strokes, styling
separate locks.
And don’t forget about the beard! Use blue and purple tints for it.

create more colorful locks

Turn off Alpha Lock on the
„hair” layer.

Use the blue, pink and yellow
colors to draw some short, bright strokes, imitating
shaved hair. Also refine the hair’s roots a little bit using
the Eraser Tool.

refine the hairstyle

Step 3

Now we need
to make a shadow for the
outer edges of the
hairstyle. Take the Selection Tool,
and select the area of the hairstyle you want
to make a little darker.

Then tap Transform, swipe down with three fingers,
and the menu will appear. Choose Copy + Paste, and you’ll get this shape on a new
layer.

Tap
the Adjustments icon and choose Hue, Saturation, Brightness from the drop-down list. Move the sliders to the left until you get the desired result. 

In
the end, make the edges softer using the Eraser Tool.

use adjustments for the shadow

use adjustments for the shadow

refine the shadows

Step 4

Let’s make the middle part of the
hairstyle a little brighter.

Select the area using the Selection Tool, tap Transform,
and Copy + Paste this shape to a new layer.

Go
to Adjustments > Hue, Saturation, Brightness, and move
the Saturation and Brightness sliders a little bit to the right. 

use adjustments for the highlights

use adjustments for the highlights

Once
we’re happy with the result, we can merge these layers.

merge layers with hairs

Step 5

Let’s add some single
strands of hair for an element of realism.

Create a New Layer for the tiny details on top of the „lines”
first. Then
pick the 6B Pencil, and draw separate
thin hairs using adjacent colors.

In the end, add some gloss to these hairs.

add tiny details to the hair

6. How to Add Volume and Texture to the Outfit

Step 1

Let’s start on the t-shirt.

First, lock in the „t-shirt” layer by activating Alpha Lock.

Take the Selection tool, and
select the lightest area of the t-shirt. Use a big size of the Soft Pastel brush and some bluish tints to
add large shapes of the highlights.

use the selection tool for the highlights

Make the edges of the highlight’s shape softer using the Eraser Tool. Also draw some
dark shadows and bright highlights, using the deep blue and soft blue-grey
colors respectively. Play around with the Opacity where possible.

add volume to the t-shirt

Now let’s distress this
punk t-shirt by adding holes.

Turn off Alpha Lock on the layer
first.

Then
use the Eraser Tool to make some holes in the fabric. Decorate
them with tiny threads. In the end, make this t-shirt a little bit more shabby
by adding some scratches to the fabric.

edgy t-shirt with holes

Step 2

Now we’ll draw the skull print on the t-shirt. 

Lock the „skull” layer by
activating Alpha Lock.

Using the Nikko Rull brush,
add some blue and green textured
strokes to the skull. Then, using the basic color
from the jacket, add some
falling shadows from the collar on both sides of the t-shirt.

draw the skull

Lower the intensity
of the pattern by reducing the Opacity of
the layer to 75%.

change opacity of the skull

Step 3

It’s time to add some volume to the jacket. Activate the Alpha Lock on this
layer as we did before.

We’ll use
the Selection Tool as a more
convenient method to add shadows and
highlights to the certain areas. Tap the or  symbols on the bottom toolbar
to add the
selected areas to each other, or subtract them accordingly.

use selection for the shadows

Choose
the color from the outlines and the Soft Pastel brush to add some shadows to
the jacket. Then use the Color Picker tool to make some smooth transitions from the shadows on the base of the jacket.

draw the jackets shadows

Step 4

Now let’s add a leather texture to the jacket.

First, apply Select to the „jacket” layer, and create a New Layer for the texture on top of it.

Choose a new Old Skin brush from the Touchups set.

choose leather texture brush

Set
the Brush Size to 100%, pick the color from the lines, and cover the whole surface
of the jacket with the texture. Just drive the
brush back and forth across the area without lifting the stylus off the
surface.

Change the Blending Mode of this layer
to Multiply, and drop the Opacity to 70%.

cover the jacket with texture

Create
a New Layer again for the highlight texture. Keep the „jacket” layer selected. Pick a pale lilac-blue
color, and add some highlights using the same Old Skin brush.

cover the jacket with texture

Step 5

Create
a New Layer for the highlights.

Pick the Soft Pastel brush again, and draw some bright highlights using the same pale lilac-blue color. Change the Brush
Size
in the process. Add some large strokes and tiny details to get an imitation
of leather.

draw the jackets highlights

Reduce the Opacity of the layer to about 75%.

play with the opacity of the highlights

Step 6

Let’s add some necessary details.

First,
create a New Layer for
reflections. Now
eye-drop the colors from the skin and t-shirt and
draw some shapes of reflections, mostly along the inner parts of the collar. Use
the Soft Pastel brush with 60% Opacity.

Also, add some soft atmospheric
pink light from the background to the outer edge of the jacket.

add reflections to the jacket

Create a New Layer again for the
glare.

Draw some bright highlights and gloss using a pale grey
color. It’s a very easy way to get the effect of shining leather.

In the end, add
some scratches to the jacket’s surface.

add some gloss to the jacket

Step 7

For a
convenient work process, let’s create a Layers
Folder
 or Group with
all the jacket layers.

Drag
these layers from left to right to
select them. Then tap the lines in the top right, and you’ll get a New Group.
Rename it „jacket”.

You can open or close this folder—just tap the little arrow in
front of the group name.

create a folder with layers

Step 8

Let’s move to the silver earrings and rivets.

Apply Alpha Lock to
the „accessories” layer. Use dark purple-blue tints to
draw the shadows
and lilac-blue
color for the highlights. Also add some metal gloss to these details.

draw the silver earrings

draw the silver rivets

In the end, add some reflections from the nearby
objects such as the skin, hair, and background.

add some reflections to accessories

Step 9

This way, we’ll add
some volume to the last earring and the badges. Don’t be afraid to use bold colors for the highlights and reflections.

draw the earring

draw the badge

Step 10

Let’s refine the whole image a little bit. Add more pink backlight to the edges of the collar and
the hairstyle to fit your character into the background better.

And here’s what we’ve got!

finish the character

7. How to Create an Abstract Background

Step 1

We already have the basic dark purple color
on our default background layer. Let’s make it a little bit darker.

change the basic color of background

Then reduce the Opacity of the „background” layer to about 40%.
It will serve as a substrate in adding some texture to the background.

change the opacity of the backgrounds shape

Step 2

Let’s add some texture and a pattern to give your image more of a grunge style.

Create a New Layer on
top of „background”, and rename it „texture”.

Pick a new brush, Rad, from the Retro set
and the same saturated pink color to add a pattern to the background. Feel free to place them in whatever manner you find
best.

Reduce the Opacity of
the layer to about 75%.

choose the brush for the backgrounds pattern

draw the backgrounds pattern

This way, add some
blue spots on the New Layer as well.

add more details to the background

We’re Finished!

I like this punk-rock style so much!

It
was a time-consuming process, but at the same time, it’s very interesting.

Thank
you for creating and experimenting with me. Enjoy and share your result!

final image

Want more tutorials on learning Procreate? Why not check out these: