Tag Archives: feature

Thumbnail

Creating The Feature Queries Manager DevTools Extension




Creating The Feature Queries Manager DevTools Extension

Ire Aderinokun



Within the past couple of years, several game-changing CSS features have been rolled out to the major browsers. CSS Grid Layout, for example, went from 0 to 80% global support within the span of a few months, making it an incredibly useful and reliable tool in our arsenal. Even though the current support for a feature like CSS Grid Layout is relatively great, not all recent or current browsers support it. This means it’s very likely that you and I will currently be developing for a browser in which it is not supported.

The modern solution to developing for both modern and legacy browsers is feature queries. They allow us to write CSS that is conditional on browser support for a particular feature. Although working with feature queries is almost magical, testing them can be a pain. Unlike media queries, we can’t easily simulate the different states by just resizing the browser. That’s where the Feature Queries Manager comes in, an extension to DevTools to help you easily toggle your feature query conditions. In this article, I will cover how I built this extension, as well as give an introduction to how developer tools extensions are built.

Working With Unsupported CSS

If a property-value pair (e.g. display: grid), is not supported by the browser the page is viewed in, not much happens. Unlike other programming languages, if something is broken or unsupported in CSS, it only affects the broken or unsupported rule, leaving everything else around it intact.

Let’s take, for example, this simple layout:

The layout in a supporting browser


Large preview

We have a header spanning across the top of the page, a main section directly below that to the left, a sidebar to the right, and a footer spanning across the bottom of the page.

Here’s how we could create this layout using CSS Grid:

See the Pen layout-grid by Ire Aderinokun (@ire) on CodePen.

In a supporting browser like Chrome, this works just as we want. But if we were to view this same page in a browser that doesn’t support CSS Grid Layout, this is what we would get:

The layout in an unsupporting browser


Large preview

It is essentially the same as if we had not applied any of the grid-related styles in the first place. This behavior of CSS was always intentional. In the CSS specification, it says:

In some cases, user agents must ignore part of an illegal style sheet, [which means to act] as if it had not been there

Historically, the best way to handle this has been to make use of the cascading nature of CSS. According to the specification, “the last declaration in document order wins.” This means that if there are multiple of the same property being defined within a single declaration block, the latter prevails.

For example, if we have the follow declarations:

body 
  display: flex;
  display: grid;

Assuming both Flexbox and Grid are supported in the browser, the latter — display: grid — will prevail. But if Grid is not supported by the browser, then that rule is ignored, and any previous valid and supported rules, in this case display: flex, are used instead.

body 
  display: flex;
  display: grid;

Cascading Problems

Using the cascade as a method for progressive enhancement is and has always been incredibly useful. Even today, there is no simpler or better way to handle simple one-liner fallbacks, such as this one for applying a solid colour where the rgba() syntax is not supported.

div 
    background-color: rgb(0,0,0);
    background-color: rgba(0,0,0,0.5);

Using the cascade, however, has one major limitation, which comes into play when we have multiple, dependent CSS rules. Let’s again take the layout example. If we were to attempt to use this cascade technique to create a fallback, we would end up with competing CSS rules.

See the Pen layout-both by Ire Aderinokun (@ire) on CodePen.

In the fallback solution, we need to use certain properties such as margins and widths, that aren’t needed and in fact interfere with the “enhanced” Grid version. This makes it difficult to rely on the cascade for more complex progressive enhancement.

Feature Queries To The Rescue!

Feature queries solve the problem of needing to apply groups of styles that are dependent on the support of a CSS feature. Feature queries are a “nested at-rule” which, like the media queries we are used to, allow us to create a subset of CSS declarations that are applied based on a condition. Unlike media queries, whose condition is dependent on device and screen specs, feature query conditions are instead based on if the browser supports a given property-value pair.

A feature query is made up of three parts:

  1. The @supports keyword
  2. The condition, e.g. display: flex
  3. The nested CSS declarations.

Here is how it looks:

@supports (display: grid) 
    body  display: grid; 
}

If the browser supports display: grid, then the nested styles will apply. If the browser does not support display: grid, then the block is skipped over entirely.

The above is an example of a positive condition within a feature query, but there are four flavors of feature queries:

  1. Positive condition, e.g. @supports (display grid)

  2. Negative condition, e.g. @supports not (display: grid)

  3. Conjunction, e.g. @supports (display:flex) and (display: grid)

  4. Disjunction, e.g. @supports (display:-ms-grid) or (display: grid)

Feature queries solve the problem of having separate fallback and enhancement groups of styles. Let’s see how we can apply this to our example layout:

See the Pen Run bunny run by Ire Aderinokun (@ire) on CodePen.

Introducing The Feature Queries Manager

When we write media queries, we test them by resizing our browser so that the styles at each breakpoint apply. So how do we test feature queries?

Since feature queries are dependent on whether a browser supports a feature, there is no easy way to simulate the alternative state. Currently, the only way to do this would be to edit your code to invalidate/reverse the feature query.

For example, if we wanted to simulate a state in which CSS Grid is not supported, we would have to do something like this:

/* fallback styles here */

@supports (display: grrrrrrrrid) 
    /* enhancement styles here */

This is where the Feature Queries Manager comes in. It is a way to reverse your feature queries without ever having to manually edit your code.

(Large preview)

It works by simply negating the feature query as it is written. So the following feature query:

@supports (display: grid) 
    body  display: grid; 
}

Will become the following:

@supports not (display: grid) 
    body  display: grid; 
}

Fun fact, this method works for negative feature queries as well. For example, the following negative feature query:

@supports not (display: grid) 
    body  display: block; 
}

Will become the following:

@supports not (not (display: grid)) 
    body  display: block; 
}

Which is actually essentially the same as removing the “not” from the feature query.

@supports (display: grid) 
    body  display: block; 
}

Building The Feature Queries Manager

FQM is an extension to your browser’s Developer Tools. It works by registering all the CSS on a page, filtering out the CSS that is nested within a feature query, and giving us the ability to toggle the normal or “inverted” version of that feature query.

Creating A DevTools Panel

Before I go on to how I specifically built the FQM, let’s cover how to create a new DevTools panel in the first place. Like any other browser extension, we register a DevTools extension with the manifest file.


  "manifest_version": 2,
  "name": "Feature Queries Manager",
  "short_name": "FQM",
  "description": "Manage and toggle CSS on a page behind a @supports Feature Query.",
  "version": "0.1",
  "permissions": [
    "tabs",
    "activeTab",
    "<all_urls>"
  ],
  "icons": 
    "128": "images/icon@128.png",
    "64": "images/icon@64.png",
    "16": "images/icon@16.png",
    "48": "images/icon@48.png"
  
}

To create a new panel in DevTools, we need two files — a devtools_page, which is an HTML page with an attached script that registers the second file, panel.html, which controls the actual panel in DevTools.

The devtools script creates the panel page


Large preview

First, we add the devtools_page to our manifest file:


  "manifest_version": 2,
  "name": "Feature Queries Manager",
  ...
  "devtools_page": "devtools.html",

Then, in our devtools.html file, we create a new panel in DevTools:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8"></head>
<body>
<!-- Note: I’m using the browser-polyfill to be able to use the Promise-based WebExtension API in Chrome -->
<script src="../browser-polyfill.js"></script>

<!-- Create FQM panel -->
<script>
browser.devtools.panels.create("FQM", "images/icon@64.png", "panel.html");
</script>
</body>
</html

Finally, we create our panel HTML page:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8"></head>
<body>
  <h1>Hello, world!</h1>
</body>
</html>

If we open up our browser, we will see a new panel called “FQM” which loads the panel.html page.

A new panel in browser DevTools showing the “Hello, World” text


Large preview

Reading CSS From The Inspected Page

In the FQM, we need to access all the CSS referenced in the inspected document in order to know which are within feature queries. However, our DevTools panel doesn’t have direct access to anything on the page. If we want access to the inspected document, we need a content script.

The content script reads CSS from the HTML document


Large preview

A content script is a javascript file that has the same access to the html page as any other piece of javascript embedded within it. To register a content script, we just add it to our manifest file:


      "manifest_version": 2,
      "name": "Feature Queries Manager",
      ...
      "content_scripts": [
        "matches": [""],
        "js": ["browser-polyfill.js", "content.js"]
      ],
    }

In our content script, we can then read all the stylesheets and css within them by accessing document.styleSheets:

Array.from(document.styleSheets).forEach((stylesheet) => 
      let cssRules;
      
      try 
        cssRules = Array.from(stylesheet.cssRules);
       catch(err) 
        return console.warn(`[FQM] Can't read cssRules from stylesheet: $ stylesheet.href `);
      }
      
      cssRules.forEach((rule, i) => 
      
        /* Check if css rule is a Feature Query */
        if (rule instanceof CSSSupportsRule) 
          /* do something with the css rule */
        
        
      });
    });

Connecting The Panel And The Content Scripts

Once we have the rules from the content script, we want to send them over to the panel so they can be visible there. Ideally, we would want something like this:

The content script passes information to the panel and the panel sends instructions to modify CSS back to the content


Large preview

However, we can’t exactly do this, because the panel and content files can’t actually talk directly to each other. To pass information between these two files, we need a middleman — a background script. The resulting connection looks something like this:

The content and panel scripts communicate via a background script


Large preview

As always, to register a background script, we need to add it to our manifest file:


  "manifest_version": 2,
  "name": "Feature Queries Manager",
  ...
  "background": 
    "scripts": ["browser-polyfill.js", "background.js"]
  ,
}

The background file will need to open up a connection to the panel script and listens for messages coming from there. When the background file receives a message from the panel, it passes it on to the content script, which is listening for messages from the background. The background script waits for a response from the content script and relays that message back to the panel.

Here’s a basic of example of how that works:

// Open up a connection to the background script
const portToBackgroundScript = browser.runtime.connect();

// Send message to content (via background)
portToBackgroundScript.postMessage("Hello from panel!");

// Listen for messages from content (via background)
portToBackgroundScript.onMessage.addListener((msg) => 
  console.log(msg);
  // => "Hello from content!"
);
// backrgound.js

// Open up a connection to the panel script
browser.runtime.onConnect.addListener((port) => 
  
  // Listen for messages from panel
  port.onMessage.addListener((request) => 
  
    // Send message from panel.js -> content.js
    // and return response from content.js -> panel.js
    browser.tabs.sendMessage(request.tabId, request)
      .then((res) => port.postMessage(res));
  );
});
// content.js

// Listen for messages from background
browser.runtime.onMessage.addListener((msg) => 

  console.log(msg)
  // => "Hello from panel!"
  
  // Send message to panel
  return Promise.resolve("Hello from content!");
);

Managing Feature Queries

Lastly, we can get to the core of what the extension does, which is to “toggle” on/off the CSS related to a feature query.

If you recall, in the content script, we looped through all the CSS within feature queries. When we do this, we also need to save certain information about the CSS rule:

  1. The rule itself
  2. The stylesheet it belongs to
  3. The index of the rule within the stylesheet
  4. An “inverted” version of the rule.

This is what that looks like:

cssRules.forEach((rule, i) => 
  
  const cssRule = rule.cssText.substring(rule.cssText.indexOf(""));
  const invertedCSSText = `@supports not ( $ rule.conditionText  ) $ cssRule `;
  
  FEATURE_QUERY_DECLARATIONS.push( 
    rule: rule,
    stylesheet: stylesheet,
    index: i, 
    invertedCSSText: invertedCSSText
  );
  
});

When the content script receives a message from the panel to invert all declarations relating to the feature query condition, we can easily replace the current rule with the inverted one (or vice versa).

function toggleCondition(condition, toggleOn) 
  FEATURE_QUERY_DECLARATIONS.forEach((declaration) => 
    if (declaration.rule.conditionText === condition) 
      
      // Remove current rule
      declaration.stylesheet.deleteRule(declaration.index);
      
      // Replace at index with either original or inverted declaration
      const rule = toggleOn ? declaration.rule.cssText : declaration.invertedCSSText;
      declaration.stylesheet.insertRule(rule, declaration.index);
        
  });
}

And that is essentially it! The Feature Query Manager extension is currently available for Chrome and Firefox.

Limitations Of The FQM

The Feature Queries Manager works by “inverting” your feature queries, so that the opposite condition applies. This means that it cannot be used in every scenario.

Fallbacks

If your “enhancement” CSS is not written within a feature query, then the extension cannot be used as it is dependent on finding a CSS supports rule.

Unsupported Features

You need to take note of if the browser you are using the FQM in does or does not support the feature in question. This is particularly important if your original feature query is a negative condition, as inverting it will turn it into a positive condition. For example, if you wrote the following CSS:

div  background-color: blue; 

@supports not (display: grid) 
  div  background-color: pink; 
}

If you use the FQM to invert this condition, it will become the following:

div  background-color: blue; 

@supports (display: grid) 
  div  background-color: pink; 
}

For you to be able to actually see the difference, you would need to be using a browser which does in fact support display: grid.

I built the Feature Queries Manager as a way to more easily test the different CSS as I develop, but it isn’t a replacement for testing layout in the actual browsers and devices. Developer tools only go so far, nothing beats real device testing.

Smashing Editorial
(ra, yk, il)


Continued: 

Creating The Feature Queries Manager DevTools Extension

Best Practices With CSS Grid Layout




Best Practices With CSS Grid Layout

Rachel Andrew



An increasingly common question — now that people are using CSS Grid Layout in production — seems to be “What are the best practices?” The short answer to this question is to use the layout method as defined in the specification. The particular parts of the spec you choose to use, and indeed how you combine Grid with other layout methods such as Flexbox, is down to what works for the patterns you are trying to build and how you and your team want to work.

Looking deeper, I think perhaps this request for “best practices” perhaps indicates a lack of confidence in using a layout method that is very different from what came before. Perhaps a concern that we are using Grid for things it wasn’t designed for, or not using Grid when we should be. Maybe it comes down to worries about supporting older browsers, or in how Grid fits into our development workflow.

In this article, I’m going to try and cover some of the things that either could be described as best practices, and some things that you probably don’t need to worry about.

The Survey

To help inform this article, I wanted to find out how other people were using Grid Layout in production, what were the challenges they faced, what did they really enjoy about it? Were there common questions, problems or methods being used. To find out, I put together a quick survey, asking questions about how people were using Grid Layout, and in particular, what they most liked and what they found challenging.

In the article that follows, I’ll be referencing and directly quoting some of those responses. I’ll also be linking to lots of other resources, where you can find out more about the techniques described. As it turned out, there was far more than one article worth of interesting things to unpack in the survey responses. I’ll address some of the other things that came up in a future post.

Accessibility

If there is any part of the Grid specification that you need to take care when using, it is when using anything that could cause content re-ordering:

“Authors must use order and the grid-placement properties only for visual, not logical, reordering of content. Style sheets that use these features to perform logical reordering are non-conforming.”

Grid Specification: Re-ordering and Accessibility

This is not unique to Grid, however, the ability to rearrange content so easily in two dimensions makes it a bigger problem for Grid. However, if using any method that allows content re-ordering — be that Grid, Flexbox or even absolute positioning — you need to take care not to disconnect the visual experience from how the content is structured in the document. Screen readers (and people navigating around the document using a keyboard only) are going to be following the order of items in the source.

The places where you need to be particularly careful are when using flex-direction to reverse the order in Flexbox; the order property in Flexbox or Grid; any placement of Grid items using any method, if it moves items out of the logical order in the document; and using the dense packing mode of grid-auto-flow.

For more information on this issue, see the following resources:

Which Grid Layout Methods Should I Use?

”With so much choice in Grid, it was a challenge to stick to a consistent way of writing it (e.g. naming grid lines or not, defining grid-template-areas, fallbacks, media queries) so that it would be maintainable by the whole team.”

Michelle Barker working on wbsl.com

When you first take a look at Grid, it might seem overwhelming with so many different ways of creating a layout. Ultimately, however, it all comes down to things being positioned from one line of the grid to another. You have choices based on the of layout you are trying to achieve, as well as what works well for your team and the site you are building.

There is no right or wrong way. Below, I will pick up on some of the common themes of confusion. I’ve also already covered many other potential areas of confusion in a previous article “Grid Gotchas and Stumbling Blocks.”

Should I Use An Implicit Or Explicit Grid?

The grid you define with grid-template-columns and grid-template-rows is known as the Explicit Grid. The Explicit Grid enables the naming of lines on the Grid and also gives you the ability to target the end line of the grid with -1. You’ll choose an Explicit Grid to do either of these things and in general when you have a layout all designed and know exactly where your grid lines should go and the size of the tracks.

I use the Implicit Grid most often for row tracks. I want to define the columns but then rows will just be auto-sized and grow to contain the content. You can control the Implicit Grid to some extent with grid-auto-columns and grid-auto-rows, however, you have less control than if you are defining everything.

You need to decide whether you know exactly how much content you have and therefore the number of rows and columns — in which case you can create an Explicit Grid. If you do not know how much content you have, but simply want rows or columns created to hold whatever there is, you will use the Implicit Grid.

Nevertheless, it’s possible to combine the two. In the below CSS, I have defined three columns in the Explicit Grid and three rows, so the first three rows of content will be the following:

  • A track of at least 200px in height, but expanding to take content taller,
  • A track fixed at 400px in height,
  • A track of at least 300px in height (but expands).

Any further content will go into a row created in the Implicit Grid, and I am using the grid-auto-rows property to make those tracks at least 300px tall, expanding to auto.

.grid   
  display: grid;  
  grid-template-columns: 1fr 3fr 1fr;  
  grid-template-rows: minmax(200px auto) 400px minmax(300px, auto);  
  grid-auto-rows: minmax(300px, auto);  
  grid-gap: 20px;  

A Flexible Grid With A Flexible Number Of Columns

By using Repeat Notation, autofill, and minmax you can create a pattern of as many tracks as will fit into a container, thus removing the need for Media Queries to some extent. This technique can be found in this video tutorial, and also demonstrated along with similar ideas in my recent article “Using Media Queries For Responsive Design In 2018.”

Choose this technique when you are happy for content to drop below earlier content when there is less space, and are happy to allow a lot of flexibility in sizing. You have specifically asked for your columns to display with a minimum size, and to auto fill.

There were a few comments in the survey that made me wonder if people were choosing this method when they really wanted a grid with a fixed number of columns. If you are ending up with an unpredictable number of columns at certain breakpoints, you might be better to set the number of columns — and redefine it with media queries as needed — rather than using auto-fill or auto-fit.

Which Method Of Track Sizing Should I Use?

I described track sizing in detail in my article “How Big Is That Box? Understanding Sizing In Grid Layout,” however, I often get questions as to which method of track sizing to use. Particularly, I get asked about the difference between percentage sizing and the fr unit.

If you simply use the fr unit as specced, then it differs from using a percentage because it distributes available space. If you place a larger item into a track then the way the fr until will work is to allow that track to take up more space and distribute what is left over.

.grid 
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-gap: 20px;


A three column layout, the first column is wider


The first column is wider as Grid has assigned it more space.

To cause the fr unit to distribute all of the space in the grid container you need to give it a minimum size of 0 using minmax().

.grid 
    display: grid;
    grid-template-columns: minmax(0,1fr) minmax(0,1fr) minmax(0,1fr);
    grid-gap: 20px;

three equal columns with the first overflowing


Forcing a 0 minimum may cause overflows

So you can choose to use fr in either of these scenarios: ones where you do want space distribution from a basis of auto (the default behavior), and those where you want equal distribution. I would typically use the fr unit as it then works out the sizing for you, and enables the use of fixed width tracks or gaps. The only time I use a percentage instead is when I am adding grid components to an existing layout that uses other layout methods too. If I want my grid components to line up with a float- or flex-based layout which is using percentages, using them in my grid layout means everything uses the same sizing method.

Auto-Place Items Or Set Their Position?

You will often find that you only need to place one or two items in your layout, and the rest fall into place based on content order. In fact, this is a really good test that you haven’t disconnected the source and visual display. If things pretty much drop into position based on auto-placement, then they are probably in a good order.

Once I have decided where everything goes, however, I do tend to assign a position to everything. This means that I don’t end up with strange things happening if someone adds something to the document and grid auto-places it somewhere unexpected, thus throwing out the layout. If everything is placed, Grid will put that item into the next available empty grid cell. That might not be exactly where you want it, but sat down at the end of your layout is probably better than popping into the middle and pushing other things around.

Which Positioning Method To Use?

When working with Grid Layout, ultimately everything comes down to placing items from one line to another. Everything else is essentially a helper for that.

Decide with your team if you want to name lines, use Grid Template Areas, or if you are going to use a combination of different types of layout. I find that I like to use Grid Template Areas for small components in particular. However, there is no right or wrong. Work out what is best for you.

Grid In Combination With Other Layout Mechanisms

Remember that Grid Layout isn’t the one true layout method to rule them all, it’s designed for a certain type of layout — namely two-dimensional layout. Other layout methods still exist and you should consider each pattern and what suits it best.

I think this is actually quite hard for those of us used to hacking around with layout methods to make them do something they were not really designed for. It is a really good time to take a step back, look at the layout methods for the tasks they were designed for, and remember to use them for those tasks.

In particular, no matter how often I write about Grid versus Flexbox, I will be asked which one people should use. There are many patterns where either layout method makes perfect sense and it really is up to you. No-one is going to shout at you for selecting Flexbox over Grid, or Grid over Flexbox.

In my own work, I tend to use Flexbox for components where I want the natural size of items to strongly control their layout, essentially pushing the other items around. I also often use Flexbox because I want alignment, given that the Box Alignment properties are only available to use in Flexbox and Grid. I might have a Flex container with one child item, in order that I can align that child.

A sign that perhaps Flexbox isn’t the layout method I should choose is when I start adding percentage widths to flex items and setting flex-grow to 0. The reason to add percentage widths to flex items is often because I’m trying to line them up in two dimensions (lining things up in two dimensions is exactly what Grid is for). However, try both, and see which seems to suit the content or design pattern best. You are unlikely to be causing any problems by doing so.

Nesting Grid And Flex Items

This also comes up a lot, and there is absolutely no problem with making a Grid Item also a Grid Container, thus nesting one grid inside another. You can do the same with Flexbox, making a Flex Item and Flex Container. You can also make a Grid Item and Flex Container or a Flex Item a Grid Container — none of these things are a problem!

What we can’t currently do is nest one grid inside another and have the nested grid use the grid tracks defined on the overall parent. This would be very useful and is what the subgrid proposals in Level 2 of the Grid Specification hope to solve. A nested grid currently becomes a new grid so you would need to be careful with sizing to ensure it aligns with any parent tracks.

You Can Have Many Grids On One Page

A comment popped up a few times in the survey which surprised me, there seems to be an idea that a grid should be confined to the main layout, and that many grids on one page were perhaps not a good thing. You can have as many grids as you like! Use grid for big things and small things, if it makes sense laid out as a grid then use Grid.

Fallbacks And Supporting Older Browsers

“Grid used in conjunction with @supports has enabled us to better control the number of layout variations we can expect to see. It has also worked really well with our progressive enhancement approach meaning we can reward those with modern browsers without preventing access to content to those not using the latest technology.”

Joe Lambert working on rareloop.com

In the survey, many people mentioned older browsers, however, there was a reasonably equal split between those who felt that supporting older browsers was hard and those who felt it was easy due to Feature Queries and the fact that Grid overrides other layout methods. I’ve written at length about the mechanics of creating these fallbacks in “Using CSS Grid: Supporting Browsers Without Grid.”

In general, modern browsers are far more interoperable than their earlier counterparts. We tend to see far fewer actual “browser bugs” and if you use HTML and CSS correctly, then you will generally find that what you see in one browser is the same as in another.

We do, of course, have situations in which one browser has not yet shipped support for a certain specification, or some parts of a specification. With Grid, we have been very fortunate in that browsers shipped Grid Layout in a very complete and interoperable way within a short time of each other. Therefore, our considerations for testing tend to be to need to test browsers with Grid and without Grid. You may also have chosen to use the -ms prefixed version in IE10 and IE11, which would then require testing as a third type of browser.

Browsers which support modern Grid Layout (not the IE version) also support Feature Queries. This means that you can test for Grid support before using it.

Testing Browsers That Don’t Support Grid

When using fallbacks for browsers without support for Grid Layout (or using the -ms prefixed version for IE10 and 11), you will want to test how those browsers render Grid Layout. To do this, you need a way to view your site in an example browser.

I would not take the approach of breaking your Feature Query by checking for support of something nonsensical, or misspelling the value grid. This approach will only work if your stylesheet is incredibly simple, and you have put absolutely everything to do with your Grid Layout inside the Feature Queries. This is a very fragile and time-consuming way to work, especially if you are extensively using Grid. In addition, an older browser will not just lack support for Grid Layout, there will be other CSS properties unsupported too. If you are looking for “best practice” then setting yourself up so you are in a good position to test your work is high up there!

There are a couple of straightforward ways to set yourself up with a proper method of testing your fallbacks. The easiest method — if you have a reasonably fast internet connection and don’t mind paying a subscription fee — is to use a service such as BrowserStack. This is a service that enables viewing of websites (even those in development on your computer) on a whole host of real browsers. BrowserStack does offer free accounts for open-source projects.


Screenshot of the download page


You can download Virtual Machines for testing from Microsoft.

To test locally, my suggestion would be to use a Virtual Machine with your target browser installed. Microsoft offers free Virtual Machine downloads with versions of IE back to IE8, and also Edge. You can also install onto the VM an older version of a browser with no Grid support at all. For example by getting a copy of Firefox 51 or below. After installing your elderly Firefox, be sure to turn off automatic updates as explained here as otherwise it will quietly update itself!

You can then test your site in IE11 and in non-supporting Firefox on one VM (a far less fragile solution than misspelling values). Getting set up might take you an hour or so, but you’ll then be in a really good place to test your fallbacks.

Unlearning Old Habits

“It was my first time to use Grid Layout, so there were a lot of concepts to learn and properties understand. Conceptually, I found the most difficult thing to unlearn all the stuff I had done for years, like clearing floats and packing everything in container divs.”

Hidde working on hiddedevries.nl/en

Many of the people responding to the survey mentioned the need to unlearn old habits and how learning Layout would be easier for people completely new to CSS. I tend to agree. When teaching people in person complete beginners have little problem using Grid while experienced developers try hard to return grid to a one-dimensional layout method. I’ve seen attempts at “grid systems” using CSS Grid which add back in the row wrappers needed for a float or flex-based grid.

Don’t be afraid to try out new techniques. If you have the ability to test in a few browsers and remain mindful of potential issues of accessibility, you really can’t go too far wrong. And, if you find a great way to create a certain pattern, let everyone else know about it. We are all new to using Grid in production, so there is certainly plenty to discover and share.

“Grid Layout is the most exciting CSS development since media queries. It’s been so well thought through for real-world developer needs and is an absolute joy to use in production – for designers and developers alike.”

Trys Mudford working on trysmudford.com

To wrap up, here is a very short list of current best practices! If you have discovered things that do or don’t work well in your own situation, add them to the comments.

  1. Be very aware of the possibility of content re-ordering. Check that you have not disconnected the visual display from the document order.
  2. Test using real target browsers with a local or remote Virtual Machine.
  3. Don’t forget that older layout methods are still valid and useful. Try different ways to achieve patterns. Don’t be hung up on having to use Grid.
  4. Know that as an experienced front-end developer you are likely to have a whole set of preconceptions about how layout works. Try to look at these new methods anew rather than forcing them back into old patterns.
  5. Keep trying things out. We’re all new to this. Test your work and share what you discover.
Smashing Editorial
(il)


From:

Best Practices With CSS Grid Layout

Styling Empty Cells With Generated Content And CSS Grid Layout

A common Grid Layout gotcha is when a newcomer to the layout method wonders how to style a grid cell which doesn’t contain any content. In the current Level 1 specification, this isn’t possible since there is no way to target an empty Grid Cell or Grid Area and apply styling. This means that to apply styling, you need to insert an element.
In this article, I am going to take a look at how to use CSS Generated Content to achieve styling of empty cells without adding redundant empty elements and show some use cases where this technique makes sense.

Source:

Styling Empty Cells With Generated Content And CSS Grid Layout

Mobile App With Facial Recognition Feature: How To Make It Real

Imagine an application that can, in real time, analyze a user’s emotional response while they’re interacting with an app or website. Or imagine a home device that recognizes you and tunes in to your favorite TV channel.
Yes, today’s article is all about facial recognition technology. We’re going to share our first experience of dealing with this technology and the findings we’ve made.
Why Is Facial Recognition On The Rise?

More here: 

Mobile App With Facial Recognition Feature: How To Make It Real

Using CSS Grid: Supporting Browsers Without Grid

When using any new CSS, the question of browser support has to be addressed. This is even more of a consideration when new CSS is used for layout as with Flexbox and CSS Grid, rather than things we might consider an enhancement.
In this article, I explore approaches to dealing with browser support today. What are the practical things we can do to allow us to use new CSS now and still give a great experience to the browsers that don’t support it?

Excerpt from:

Using CSS Grid: Supporting Browsers Without Grid

Don’t Settle. Build the Marketing Campaigns of Your Dreams Without a Line of Code

Conquer technical limitations with Zapier and Unbounce

Hi, I’m Corey. Are you an idealistic marketer, like me?

That is—do you plan your marketing campaigns by pretending technical limitations aren’t a thing and just map out the ideal experience you want for your prospects from first impression to final conversion? Like this:

A photo of my actual campaign flow on the whiteboard.

If your whiteboard looks this optimistic, read on. We’ll nerd out together.

After us idealistic marketers are done dreaming about our perfect campaign structure from start to finish, the harsh reality sets in: technical limitations are definitely a thing. When the time comes to figure out how to actually do something a little crazy, like augment lead data or enrich it with extra data pulled from ‘the internet’, things get much trickier. But if you’re dedicated to the campaign you mapped out, you really want to make it happen.

Often, you’ll ask a developer for help and hear, “Sure it’s possible. I’ll just need two weeks to code it up. Log a request and we’ll prioritize it against all the other requests for my genius.”

We both know you’re not logging that request, because it’s not getting prioritized.

Eventually, you run a campaign that looks exactly like what you’ve done before, or what everyone else is doing, because it’s relatively easy for us—lowly marketers—to pull off by ourselves.

It’s infuriating.

Can’t we Execute More Sophisticated Marketing?

Is it too much to ask that we can create whatever the hell we dream up, so we can push the industry forward? To deliver the experience we think could make a difference to our prospects—one they might even enjoy?

Not if we need to rely on devs to help build our lead management or the integrations component of our campaigns for us, unfortunately.

However, I’ve found that more and more often I don’t need to have these futile conversations with developers. Modern martech has brought us tools to help, and the tool that comes up most often for me is Zapier.

Your Marketing on Zapier

Have you ever punched above your weight at work and solved a problem that that you’re totally unqualified to solve? It. feels. so. satisfying. You feel way smarter than you actually are.

I got that feeling when I used Zapier with Unbounce for the first time. I still get that feeling today. If you dream big enough, and can connect the right tools together, you can pull off campaign workflows that feel almost impossible.

Exactly how I felt having used Zapier for the first time.

Most recently, I tried to execute the campaign in the whiteboard photo above (the one above the Dragonball Z meme). The campaign—called Conversion Quest—challenges PPC marketers working in agencies to double the conversion rate of one of their client’s landing pages in 30 days.

When planning this campaign, I wanted to have a prospect fill out the form on a landing page with the current date (when they were “starting their quest”), and their current conversion rate. From there, they’d receive an email confirming their personalized quest goal and deadline by which they’d ideally complete the challenge (The email was to automatically pull in someone’s target conversion rate and their custom due date a month out).

Of course, when I’d planned this flow, there was no technical way to magically include a doubled conversion rate and custom due date directly in each prospect’s followup message. That is until my colleague reminded me of Zapier Formatter, which allows you to manipulate your lead data before it goes into your marketing automation platform (or CRM, or Email Marketing Service, or wherever other tool you can think of). Just 30 minutes later (and without approaching our dev team), I had augmented data going into our marketing automation platform.

Now Conversion Quest runs with custom info in the followup, all thanks to a quick Zap (a preconfigured integration template connecting two or more apps).

Here’s an example of the message I send in that campaign:

Here’s a sample of the email I manipulated data with via Zapier to personalize.

Now, are you going to need to use Zapier so you can build Conversion Quest?

No (that’s my great idea)… But my bet is you’ve got amazing campaign ideas for which Zaps could help you create a consistent (better!) experience for your leads, and help you stop relying on developers. As a bonus, Unbounce now has Integrations Powered by Zapier available right in the builder, so you can do this super quickly, without ever leaving Unbounce.

Here’s just a sampling of the Zaps available right in Unbounce. There are 60+ right in app, and with a Premium Zapier account you can access over 900!

Let’s dig into the versatility for a second.

Leveling up your marketing (without a line of code)

You could use Unbounce’s Integrations Powered by Zapier if…

1. You need to connect a client’s hodgepodge of tools

In this case, you’re a marketing agency that needs to build high-converting lead gen landing pages, overlays or sticky bars that connect to anything and everything your clients use, which could include:

  • Hatchbuck
  • Base
  • Follow Up Boss
  • Agile CRM
  • Pipedrive
  • Salesforce
  • HubSpot CRM
  • Capsule CRM
  • PipelineDeals

A few quick Zaps can connect your lead data to all of the above.

2. You want to use an existing CRM or marketing automation platform, with custom landing pages/Unbounce

If you’re using a tool that requires you to use rigid forms or landing pages, but you’d rather have custom landing pages that look great, convert like crazy and give you more control over the experience, you’d simply Zap together your landing page builder with tools/platforms like:

  • GoToWebinar
  • Marketo
  • Salesforce
  • Pardot
  • MailChimp
3. Your CMS or Marketing Automation tool doesn’t enrich your data for you

With Integrations Powered by Zapier, if you collect a lead in Unbounce, Zapier can enrich the lead’s profile with extra data (using, for example, the lead scoring Zap) en route to wherever you’re storing your leads.

4. Your sales team would like to be notified immediately when a super qualified lead comes in…but they never check their email

For this, you can try sending notifications via the following Zaps:

  • SMS integration
  • Slack
  • Twitter
  • LinkedIn
5. You’d like to route leads to specific salespeople in your CRM depending on the info a prospect submits in a form

Joe Savich from Altos gave this a try in Unbounce, and had high praise for this email parser Zap:

“It’s pretty nice. The integration powered by Zapier was super easy to setup…I was able to create a lead notification with a condition that, depending on which custom field was chosen, would send that lead to the appropriate sales team. My client thinks I am a magician! I could see this being used a lot going forward.”

Overall, of all the feature releases in my 4 ½ years at Unbounce, Integrations Powered by Zapier is my all time favourite. Zaps from right inside our builder empower marketers to do things you shouldn’t be able to do, without developers. And they make you feel really smart.

If you’re committed to driving our industry forward with some next-level marketing (that may look impossible at first glance), I’d urge you to try zapping some connections together and getting creative. You might surprise yourself, or better yet your boss or clients.

Continue reading: 

Don’t Settle. Build the Marketing Campaigns of Your Dreams Without a Line of Code

Send Your Unbounce Lead Data to 60+ Apps Instantly with New Integrations Powered by Zapier

Introducing Integrations Powered by Zapier

These days the average marketer has been cited to use anywhere from 12 to a whopping 31 tools to build the campaigns of their dreams, but making sure all of these different apps or tools work together like a well-oiled machine is often where things get messy.

For example, you might generate leads via your landing pages, but — depending on your marketing stack and the connections you’ve set up — it’s not always easy to automatically pass, tag and strategically route form data you’ve collected into all the different tools you need to work in (i.e. you might be using Google Sheets for lead tracking, your CRM for sales follow-up, and your marketing automation platform for triggering especially relevant email campaigns).

Maintaining a simple workflow for your lead management is next to impossible if your tools don’t connect and talk to each other properly.

Luckily, all the tools you love can talk to each other

Today at Unbounce, we’re excited to introduce our new Integrations Powered by Zapier.

Now, you can instantly connect your landing page, overlay and sticky bar lead data to over 60+ apps without typing a line of code or ever leaving the Unbounce builder.

Integrations Powered by Zapier

What’s Zapier?

If you’re not already a super fan, Zapier’s the tool over one million people use to connect their favorite web apps together for less busywork and more impressive automation. It’s like the one integration to rule them all – or the tool that makes all the other tools hold hands and play nice.

We’ve seen thousands of Unbounce customers build landing pages, overlays and sticky bars, then set up custom integrations with Zapier to funnel lead data into their other favorite tools like Intercom, Go2Webinar, Autopilot and Salesforce, for example. Today that connection’s even easier.

New: Unbounce's Integrations Powered by Zapier

Goodbye busywork, hello automation

Acting as a handy lead gen concierge, the new Integrations Powered by Zapier help eliminate mundane setup tasks.

With pre-built Zap templates directly in Unbounce and the usual integration set-up tasks automated for you, Zapier helps you get centralized lead management for any campaign in just a few clicks.

Even better? Zapier is a trade secret for leveling up the sophistication of your marketing. Using Zaps to connect your lead generation data with other tools and automate more actions, you can set up elaborate campaigns without needing to build workarounds or “hacks,” or depend on dev resources to build your integrations for you.

The possibilities are endless, but here’s a taste of how a few of our customers are already using this feature to fuel impressive campaigns without relying on IT.

Zap inspiration #1: Enrich your lead data

It’s one thing to generate new leads, it’s another if they get routed to your sales team pronto with extra context (like a lead’s unique preferences) included.

Joe Savitch, SEM and Inbound marketer at digital agency Altos, recently launched a lead gen campaign with a real estate client and wanted leads’ properties of interest included in the info submitted via the form (without the lead having to select manually from a drop down). In knowing which properties leads were expressly interested in, the real estate client’s sales team could follow up with especially relevant outreach.

Not only was Joe able to identify each lead’s specific interest using a lightbox that passed a value from the button to the lead form, but with Unbounce’s new Integrations Powered by Zapier (the “Email Parser” Zap), Joe created a lead notification that routed leads to the appropriate sales team based on which custom field had been chosen:

And here’s an example of the lead notification his team receives:

A sample of the lead notification Joe has automatically sent to the sales team via the Zap. Properties of interest are noted here for the sales team.

Joe’s verdict?

The Integration Powered by Zapier was super easy to setup and execute… My client thinks I am a magician! I could see this being used a lot going forward.

Want to push your lead data to other tools seamlessly? Get more info on the new Integrations Powered by Zapier, and see more Zaps available to you here.

Zap inspiration #2: Get visibility into campaign ROI

Serving many small to medium sized clients, Stefano Apostolakos of digital agency Webistry notes that many of the brands they work with don’t have, or aren’t familiar with sales CRM tools, meaning the agency can have a hard time demonstrating the ROI of the lead gen campaigns they run.

But now, thanks to the PipeDrive Zap directly in Unbounce, all of Webistry’s campaign leads get pushed into PipeDrive (a sales CRM), tagged and positioned appropriately in a client’s sales funnel.

Stefano’s team then runs monthly reports to discover which campaigns, ad groups and keywords achieve the highest CPA (cost per acquisition) to show the client just how valuable the new campaigns have been. Here’s what Stefano had to say about it:

Our customers have been very excited to see the direct impact their campaigns have on the bottom line. Being able to prove the value we bring has helped us to build loyalty, and generate an extensive portfolio of happy, long-term customers.

Want to set up a Zap to better see your ROI? To use Integrations Powered by Zapier, you’ll need a Zapier account and Unbounce. Learn more here.

Go forth and Zap!

This is really just the tip of the iceberg. While Unbounce now contains 60+ Zap templates to choose from right in the builder to get you started, if you have a Premium Zapier subscription, you’ll have access to over 900+ app integrations via Zapier you can make use of in Unbounce.

Whether you want to use one Zap at a time, or go wild with a few at a time (i.e. lead data pushed into Google Sheets, Slack, LinkedIn and more…), today you can finally manage, tag, and re-route all the leads you collect with Unbounce (from right in Unbounce). The only limit is your imagination.

You’ll simplify your campaign workflows, and all of your tools will run smoothly together. Not to mention, you can run far more complex campaigns without the help of IT.

We’re psyched to be the first conversion platform to make Zapier integrations available directly in the builder, and we can’t wait to see what you Zap together.

Originally posted here: 

Send Your Unbounce Lead Data to 60+ Apps Instantly with New Integrations Powered by Zapier

Uploading Directories At Once With webkitdirectory

If you’ve ever tried to implement a bulletproof, good-looking file uploader, you might have encountered an issue: uploading an entire folder or folders of files is usually quite a hassle, as files in each folder have to be selected manually. And then some folders might contain sub-folders as well.
Well, we can use webkitdirectory, a non-standard attribute that allows users to pick a directory via a file input. Currently supported in Chrome, Firefox and Edge.

Visit site – 

Uploading Directories At Once With webkitdirectory

Designing The Perfect Feature Comparison Table

Not all products are created equal. While we repeatedly buy some products almost mindlessly, for others, we take a lot of time to make a purchasing decision. For a price tag that meets a certain threshold or if we are particularly invested in the quality of a product, we want to be absolutely certain that we are making the right choice and are getting a good product for a good price.

Continue reading:  

Designing The Perfect Feature Comparison Table

Thumbnail

Glossary: Value Proposition

glossary value proposition

A value proposition is what you guarantee or promise to deliver to your potential buyers in exchange for their money. It’s also the main reason why people choose one product over other. If it’s done right, it can give you the competitive edge and help you grow your business. The value proposition is vital to conversion optimization as it allows you to build a perception of the value that a user is getting. So, if you test it, these few sentences might have a significant impact on your conversion rate and sales. What the value proposition does when done right:…

The post Glossary: Value Proposition appeared first on The Daily Egg.

Originally posted here: 

Glossary: Value Proposition