Tag: Elements

Flexbox-like “just put elements in a row” with CSS grid

It occurred to me while we were talking about flexbox and gap that one reason we sometimes reach for flexbox is to chuck some boxes in a row and space them out a little.

My brain still reaches for flexbox in that situation, and with gap, it probably will continue to do so. It’s worth noting though that grid can do the same thing in its own special way.

Like this:

.grid {   display: grid;   gap: 1rem;   grid-auto-flow: column; }

They all look equal width there, but that’s only because there is no content in them. With content, you’ll see the boxes start pushing on each other based on the natural width of that content. If you need to exert some control, you can always set width / min-width / max-width on the elements that fall into those columns — or, set them with grid-template-columns but without setting the actual number of columns, then letting the min-content dictate the width.

.grid {   display: grid;   gap: 1rem;   grid-auto-flow: column;   grid-template-columns: repeat(auto-fit, minmax(min-content, 1fr)); }

Flexible grids are the coolest.

Another thought… if you only want the whole grid itself to be as wide as the content (i.e. less than 100% or auto, if need be) then be aware that display: inline-grid; is a thing.

The post Flexbox-like “just put elements in a row” with CSS grid appeared first on CSS-Tricks.

CSS-Tricks

, , , ,

Working With MDX Custom Elements and Shortcodes

MDX is a killer feature for things like blogs, slide decks and component documentation. It allows you to write Markdown without worrying about HTML elements, their formatting and placement while sprinkling in the magic of custom React components when necessary.

Let’s harness that magic and look at how we can customize MDX by replacing Markdown elements with our own MDX components. In the process, we’ll introduce the concept of “shortcodes” when using those components.

As a heads up, the code snippets here are based on GatsbyJS and React, but MDX can be written with different frameworks as well. If you need a primer on MDX, start here first. This article extends that one with more advanced concepts.

Setting up a layout

We almost always want to render our MDX-based pages in a common layout. That way, they can be arranged with other components on our website. We can specify a default Layout component with the MDX plugin we’re using. For example. we can define a a layout with the gatsby-plugin-mdx plugin like this:

{   resolve: `gatsby-plugin-mdx`,   options: {     defaultLayouts: {       default: path.resolve('./src/templates/blog-post.js'),     },     // ...other options   } }

This would require the src/templates/blog-post.js file to contain a component that would render the children prop it receives.

import { MDXRenderer } from 'gatsby-plugin-mdx'; 
 function BlogPost({ children }) {   return (     <div>{children}</div>   ); } 
 export default BlogPost;

If we are programmatically creating pages, we’d have to use a component named MDXRenderer to achieve the same thing, as specified in the Gatsby docs.

Custom Markdown elements

While MDX is a format where that lets us write custom HTML and React components, its power is rendering Markdown with custom content. But what if we wanted to customize how these Markdown elements render on screen?

We could surely write a remark plugin for it, but MDX provides us with a better, simpler solution. By default, these are some of the elements being rendered by Markdown:

Name HTML Element MDX Syntax
Paragraph <p>
Heading 1 <h1> #
Heading 2 <h2> ##
Heading 3 <h3> ###
Heading 4 <h4> ####
Heading 5 <h5> #####
Heading 6 <h6> ######
Unordered List <ul> -
Ordered List <ol /> 1.
Image <img /> ![alt](https://image-url)
A complete list of components is available in the MDX Docs.

To replace these defaults with our custom React components, MDX ships with a Provider component named  MDXProvider. It relies on the React Context API to inject new custom components and merge them into the defaults provided by MDX.

import React from 'react'; import { MDXProvider } from "@mdx-js/react"; import Image from './image-component'; 
 function Layout({ children }) {   return (     <MDXProvider       components={{         h1: (props) => <h1 {...props} className="text-xl font-light" />         img: Image,       }}      >       {children}     </MDXProvider>   ); } 
 export default Layout;

In this example, any H1 heading (#) in the MDX file will be replaced by the custom implementation specified in the Provider component’s prop while all the other elements will continue to use the defaults. In other words, MDXProvider is able to take our custom markup for a H1 element, merge it with MDX defaults, then apply the custom markup when we write Heading 1 (#) in an MDX file.

MDX and custom components

Customizing MDX elements is great, but what if we want to introduce our own components into the mix?

--- title: Importing Components --- import Playground from './Playground'; 
 Here is a look at the `Playground` component that I have been building: 
 <Playground />

We can import a component into an MDX file and use it the same way we would any React component. And, sure, while this works well for something like a component demo in a blog post, what if we want to use Playground on all blog posts? It would be a pain to import them to all the pages. Instead. MDX presents us with the option to use shortcodes. Here’s how the MDX documentation describes shortcodes:

[A shortcode] allows you to expose components to all of your documents in your app or website. This is a useful feature for common components like YouTube embeds, Twitter cards, or anything else frequently used in your documents.

To include shortcodes in an MDX application, we have to rely on the MDXProvider component again.

import React from 'react'; import { MDXProvider } from "@mdx-js/react"; import Playground from './playground-wrapper'; 
 function Layout({ children }) {   return (     <MDXProvider       components={{         h1: (props) => <h1 {...props} className="text-xl font-light" />         Playground,       }}      >       {children}     </MDXProvider>   ); } 
 export default Layout;

Once we have included custom components into the components object, we can proceed to use them without importing in MDX files.

--- title: Demoing concepts --- 
 Here's the demo for the new concept: 
 <Playground /> 
 > Look ma! No imports

Directly manipulating child components

In React, we get top-level APIs to manipulate children with React.Children. We can use these to pass new props to child components that change their order or determine their visibility. MDX provides us a special wrapper component to access the child components passed in by MDX.

To add a wrapper, we can use the MDXProvider as we did before:

import React from "react"; import { MDXProvider } from "@mdx-js/react"; const components = {   wrapper: ({ children, ...props }) => {     const reversedChildren = React.Children.toArray(children).reverse();     return <>{reversedChildren}</>;   }, }; export default (props) => (   <MDXProvider components={components}>     <main {...props} />   </MDXProvider> );

This example reverses the children so that they appear in reverse order that we wrote it in.

We can even go wild and animate all of MDX children as they come in:

import React from "react"; import { MDXProvider } from "@mdx-js/react"; import { useTrail, animated, config } from "react-spring"; 
 const components = {   wrapper: ({ children, ...props }) => {     const childrenArray = React.Children.toArray(children);     const trail = useTrail(childrenArray.length, {       xy: [0, 0],       opacity: 1,       from: { xy: [30, 50], opacity: 0 },       config: config.gentle,       delay: 200,     });     return (       <section>         {trail.map(({ y, opacity }, index) => (           <animated.div             key={index}             style={{               opacity,               transform: xy.interpolate((x, y) => `translate3d($  {x}px,$  {y}px,0)`),             }}           >             {childrenArray[index]}           </animated.div>         ))}       </section>     );   }, }; 
 export default (props) => (   <MDXProvider components={components}>     <main {...props} />   </MDXProvider> );

Wrapping up

MDX is designed with flexibility out of the box, but extending with a plugin can make it do even more. Here’s what we were just able to do in a short amount of time, thanks to gatsby-plugin-mdx:

  1. Create default Layout components that help format the MDX output.
  2. Replace default HTML elements rendered from Markdown with custom components
  3. Use shortcodes to get rid of us of importing components in every file.
  4. Manipulate children directly to change the MDX output.

Again, this is just another drop in the bucket as far as what MDX does to help make writing content for static sites easier.

More on MDX

The post Working With MDX Custom Elements and Shortcodes appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]

Why Do Some HTML Elements Become Deprecated?

The internet has been around for a long while, and over time we’ve changed the way we think about web design. Many old techniques and ways of doing things have gotten phased out as newer and better alternatives have been created, and we say that they have been deprecated.

Deprecated. It’s a word we use and see often. But have you stopped to think about what it means in practice? What are some examples of deprecated web elements, and why don’t we use them any more?

What is deprecation?

In everyday English, to “deprecate” something is to express disapproval of it. For example, you might be inclined to deprecate a news story you don’t like.

When we’re speaking in a technical sense, however, deprecation is the discouragement of use for an old feature. Often, the old feature remains functional in the interests of backward compatibility (so legacy projects don’t break). In essence, this means that you can technically still do things the legacy way. It’ll probably still work, but maybe it’s better to use the new way. 

Another common scenario is when technical elements get deprecated as a prelude to their future removal (which we sometimes call “sunsetting” a feature). This provides everybody time to transition from the old way of working to the new system before the transition happens. If you follow WordPress at all, they recently did this with their radically new Gutenberg editor. They shipped it, but kept an option available to revert to the “classic” editor so users could take time to transition. Someday, the “classic” editor will likely be removed, leaving Gutenberg as the only option for editing posts. In other words, WordPress is sunsetting the “classic” editor.

That’s merely one example. We can also look at HTML features that were once essential staples but became deprecated at some point in time.

Why do HTML elements get deprecated?

Over the years, our way of thinking about HTML has evolved. Originally, it was an all-purpose markup language for displaying and styling content online.

Over time, as external stylesheets became more of a thing, it began to make more sense to think about web development differently — as a separation of concerns where HTML defines the content of a page, and CSS handles the presentation of it.

This separation of style and content brings numerous benefits:

  • Avoiding duplication: Repeating code for every instance of red-colored text on a page is unwieldy and inefficient when you can have a single CSS class to handle all of it at once. 
  • Ease of management: With all of the presentation controlled from a central stylesheet, you can make site-wide changes with little effort.
  • Readability: When viewing a website’s source, it’s a lot easier to understand the code that has been neatly abstracted into separate files for content and style. 
  • Caching: The vast majority of websites have consistent styling across all pages, so why make the browser download those style definitions again and again? Putting the presentation code in a dedicated stylesheet allows for caching and reuse to save bandwidth. 
  • Developer specialization: Big website projects may have multiple designers and developers working on them, each with their individual areas of expertise. Allowing a CSS specialist to work on their part of the project in their own separate files can be a lot easier for everybody involved. 
  • User options: Separating styling from content can allow the developer to easily offer display options to the end user (the increasingly popular ‘night mode’ is a good example of this) or different display modes for accessibility. 
  • Responsiveness and device independence: separating the code for content and visual presentation makes it much easier to build websites that display in very different ways on different screen resolutions.

However, in the early days of HTML there was a fair amount of markup designed to control the look of the page right alongside the content. You might see code like this: 

<center><font face="verdana" color="#2400D3">Hello world!</font></center>

…all of which is now deprecated due to the aforementioned separation of concerns. 

Which HTML elements are now deprecated?

As of the release of HTML5, use of the following elements is discouraged:

  • <acronym> (use <abbr> instead)
  • <applet> (use <object>)
  • <basefont> (use CSS font properties, like font-size, font-family, etc.)
  • <big> (use CSS font-size)
  • <center> (use CSS text-align)
  • <dir> (use <ul>)
  • <font> (use CSS font properties)
  • <frame> (use <iframe>)
  • <frameset> (not needed any more)
  • <isindex> (not needed any more)
  • <noframes> (not needed any more)
  • <s> (use text-decoration: line-through in CSS)
  • <strike> (use text-decoration: line-through in CSS)
  • <tt> (use <code>)

There is also a long list of deprecated attributes, including many elements that continue to be otherwise valid (such as the align attribute used by many elements). The W3C has the full list of deprecated attributes.

Why don’t we use table for layouts any more?

Before CSS became widespread, it was common to see website layouts constructed with the <table> element. While the <table> element is not deprecated, using them for layout is strongly discouraged. In fact, pretty much all HTML table attributes that were used for layouts have been deprecated, such as cellpadding, bgcolor and width

At one time, tables seemed to be a pretty good way to lay out a web page. We could make rows and columns any size we wanted, meaning we could put everything inside. Headers, navigation, footers… you name it!

That would create a lot of website code that looked like this:

<table border="0" cellpadding="0" cellspacing="0" width="720">   <tr>     <td colspan="10"><img name="logobar" src="logobar.jpg" width="720" height="69" border="0" alt="Logo"></td>   </tr>   <tr>     <td rowspan="2" colspan="5"><img name="something" src="something.jpg" width="495" height="19" border="0" alt="A picture of something"></td>     <td>Blah blah blah!</td>     <td colspan="3">    <tr>   <!--  and so on --> </table>

There are numerous problems with this approach:

  • Complicated layouts often end up with tables nested inside other tables, which creates a headache-inducing mess of code. Just look at the source of any email newsletter.
  • Accessibility is problematic, as screen readers tend to get befuddled by the overuse of tables.
  • Tables are slow to render, as the browser waits for the entire table to download before showing it on the screen.
  • Responsible and mobile-friendly layouts are very difficult to create with a table-based layout. We still have not found a silver bullet for responsive tables (though many clever ideas exist).

Continuing the theme of separating content and presentation, CSS is a much more efficient way to create the visual layout without cluttering the code of the main HTML document. 

So, when should we use<table>? Actual tabular data, of course! If you need to display a list of baseball scores, statistics or anything else in that vein, <table> is your friend. 

Why do we still use <b> and <i> tags?

“Hang on just a moment,” you might say. “How come bold and italic HTML tags are still considered OK? Aren’t those forms of visual styling that ought to be handled with CSS?”

It’s a good question, and one that seems difficult to answer when we consider that other tags like <center> and <s> are deprecated. What’s going on here?

The short and simple answer is that <b> and <i> would probably have been deprecated if they weren’t so widespread and useful. CSS alternatives seem somewhat unwieldy by comparison:

<style>   .emphasis { font-weight:bold } </style>      This is a <span class="emphasis">bold</span> word!  This is a <span style="font-weight:bold">bold</span> word!  This is a <b>bold</b> word!

The long answer is that these tags have now been assigned some semantic meaning, giving them value beyond pure visual presentation and allowing designers to use them to confer additional information about the text they contain.

This is important because it helps screen readers and search crawlers better understand the purpose of the content wrapped in these tags. We might italicize a word for several reasons, like adding emphasis, invoking the title of a creative work, referring to a scientific name, and so on. How does a screen reader know whether to place spoken emphasis on the word or not?

<b> and <i>have companions, including <strong>, <em> and <cite>. Together, these tags make the meaning context of text clearer:

  • <b> is for drawing attention to text without giving it any additional importance. It’s used when we want to draw attention to something without changing the inflection of the text when it is read by a screen reader or without adding any additional weight or meaning to the content for search engines.
  • <strong> is a lot like <b> but signals the importance of something. It’s the same as changing the inflection of your voice when adding emphasis on a certain word.
  • <i> italicizes text without given it any additional meaning or emphasis. It’s perfect for writing out something that is normally italicized, like the scientific name of an animal.
  • <em> is like <i> in that it italicizes text, but it provides adds additional emphasis (hence the tag name) without adding more importance in context. (‘I’m sure I didn’t forget to feed the cat’). 
  • <cite> is what we use to refer to the title of a creative work, say a movie like The Silence of the Lambs. This way, text is styled but doesn’t affect the way the sentence would be read aloud. 

In general, the rule is that <b> and <i> are to be used only as a last resort if you can’t find anything more appropriate for your needs. This semantic meaning allows <b> and <i> to continue to have a place in our modern array of HTML elements and survive the deprecation that has befallen other, similar style tags.

On a related note, <u> — the underline tag — was at one time deprecated, but has since been restored in HTML5 because it has some semantic uses (such as annotating spelling errors).

There are many other HTML elements that might lend styling to content, but primarily serve to provide semantic meaning to content. Mandy Michael has an excellent write-up that covers those and how they can be used (and even combined!) to make the most semantic markup possible.

Undead HTML attributes

Some deprecated elements are still in widespread use around the web today. After all, they still work — they’re just discouraged.

This is sometimes because word hasn’t gotten around that that thing you’ve been using for ages isn’t actually the way it’s done any more. Other times, it’s due to folks who don’t see a compelling reason to change from doing something that works perfectly well. Hey, CSS-Tricks still uses the teletype element for certain reasons.

One such undead HTML relic is the align attribute in otherwise valid tags, especially images. You may see <img> tags with a border attribute, although that attribute has long been deprecated. CSS, of course, is the preferred and modern method for that kind of styling presentation.


Staying up to date with deprecation is key for any web developer. Making sure your code follows the current recommendations while avoiding legacy elements is an essential best practice. It not only ensures that your site will continue to work in the long run, but that it will play nicely with the web of the future.

Questions? Post a comment! You can also find me over at Angle Studios where I work.

The post Why Do Some HTML Elements Become Deprecated? appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]

Toward Responsive Elements

Hot news from Brian Kardell, regarding what we’ve been referring to as “container queries”, the most hotly requested feature in CSS:

There does seem to be some general agreement on at least one part of what I am going to call instead “Responsive Design for Components” and that is that flipping the problem on its head is better.

The flipping here sounds like instead of doing it as media query, we do it at the property level.

.foo {   display: grid;   grid-template-columns: switch(     (available-inline-size > 1024px) 1fr 4fr 1fr;     (available-inline-size > 400px) 2fr 1fr;     (available-inline-size > 100px) 1fr;     default 1fr;   ); }

I think this is still in the ideation phase, and other people are ideating as well on different ideas, but this seems worth sharing to me as it sounds like it has traction and is doable because it isn’t plagued with well that’s just not how browsers work that came up a lot with container queries.

Brian also talks about “lightspeed progress” lately, for example:

Consider that we shifted the stalemate conversation and ResizeObserver was envisioned, incubated, speced, tested, agreed upon, iterated on (we got things wrong!) and implemented in all browsers in about 2 years

Two years is smokin’ in standards.

Direct Link to ArticlePermalink

The post Toward Responsive Elements appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

Full-Width Elements By Using Edge-to-Edge Grid

If you have a limited-width container, say a centered column of text, “breaking out” of that to make a full-width element involves trickery. Perhaps the best trick is the one with left relative positioning and a negative left viewport-based margin. While it has it’s caveats (e.g. requiring hidden overflow on the body, the container needs to be centered, etc.), at least it’s easy to pull off and everything else in the container just happily goes about its business.

There have been quite a few posts about another way to do this, involving CSS grid:

The one thing that all these have in common is that they presuppose you have an edge-to-edge grid. I kept thinking to myself, “Do people really use CSS grid for their entire page layout?” Like, essentially body { display: grid; }¹? The articles themselves tend to use a class name, but the assumption is that that parent is a full-browser-width container.

I asked around a little, and there was some murmurs of, “yes, I totally do that.” So, cool, it’s a thing people do. My first thought was that that seems like a pain in the butt for a few of reasons:

  1. A typical “header” and “footer” are full-width, so having to explicitly place them on the grid and stretch them over the correct number of columns and keep that up to date as you fiddle with the columns seems like a lot of work compared to having the header just be a block-level <header> sitting at the top (or bottom) of the site. You can still have an edge-to-edge grid in the middle, and have block-level elements above and below.
  2. Having to explicitly place all the items in an “article” into a middle column (e.g. article > * { grid-columns: 2 / 3; } just so you can occasionally “stretch” something by spanning more columns just feels weird to me. Like, if 95% of content lives in a centered column, something feels both more robust and relaxed about just putting that content into a parent element that handles the layout, rather than having each individual element needing to place itself onto the grid and the end result is that it appears as if it’s all in a shared parent.

I’m not hating on the technique necessarily, just noting that it makes me feel weird somehow. But I’m probably just old.

  1. I’d advise never using display: grid; directly on the body element. One common problem: browser extensions might place things into the DOM within the body, which would then be placed onto your grid and could screw up your layout. Seen it happen. I’d say it’s just like the React best practice not to bind the whole body, but to use a div child that is effectively the same thing anyway, just scoped to a selector.

The post Full-Width Elements By Using Edge-to-Edge Grid appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]

How to Stack Elements in CSS

If you want to create fantastic and unique visual experiences on the web, you will eventually need two elements to overlap or exist in the same place. You may even just need them to be positioned near or next to each other. Let’s go over two different ways to accomplish this, one with the position property and one with CSS Grid.

Method 1: Using the Position Property

You may already know that position: absolute; will place something absolutely on the page wherever you want it to be. In this case, we’re absolutely positioning the child to the top-left of the page. No matter where the parent is, the child will be placed in that corner, absolutely.

.child {   ...   position: absolute;   top: 0;   left: 0; }

See the Pen
CSS Stacking, Absolute 1
by Sarah Drasner (@sdras)
on CodePen.

But this is very brittle! What if you were to place something on the page and then something else comes along after it? Maybe you have an icon within a navigation that you always want in the top-left corner, but a third party comes in and puts in a banner ad. (I’m not advocating for banner ads, but they do exist.) This pushes the navigation down and now the icon is out of place.

Or, let’s say you want to make a self-contained component that you can use in multiple places. You need it to be reusable and work within its own context, no matter where you use it.

If we put position: relative; on the parent element, anything inside of it with position: absolute; will be placed absolutely, relative to that containing unit!

.child {   /* ... */   position: absolute;   top: 0;   left: 0; }  .parent {   position: relative; }

See the Pen
CSS Stacking, Absolute 2
by Sarah Drasner (@sdras)
on CodePen.

Nice.

We can use this same premise if we wanted to stack two elements on top of each other. Here, we’ll have two child elements stacked on top of one another and set apart by 150 pixels. We’ll see that they’re now contained in that same parent and stay positioned inside it.

<div class="parent">   <h2>Parent</h2>    <div class="child child-1">     <h2>Child 1</h2>   </div>    <div class="child child-2">     <h2>Child 2</h2>   </div> </div>
.child {   position: absolute;   top: 0; }  .child-1 {   left: 0; }  .child-2 {   left: 150px; }  .parent {   position: relative; }

See the Pen
CSS Stacking, Absolute 3
by Sarah Drasner (@sdras)
on CodePen.

This is a little old school, but I’ve been using it for years and I still reach for it. It works consistently across browsers and can help you achieve even the strangest and unique placements.

Method 2: Using CSS Grid

Another nice way of overlapping elements, stacking them, or modifying their placement is CSS Grid, depending on how far back you need to support (which you can check with caniuse).

We can place something where we need it in the container like this:

.parent {   display: grid;   grid-template-columns: 250px 1fr;   grid-template-rows: 150px 1fr; }  .child {   grid-area: 1 / 1 / 2 / 2; }

See the Pen
CSS Stacking, Grid 1
by Sarah Drasner (@sdras)
on CodePen.

And if one element should stack on the other, we can put them in the exact same grid area. Let’s also offset them slightly by using a margin.

.parent {   display: grid;   grid-template-columns: 250px 1fr;   grid-template-rows: 150px 1fr; }  .child {   grid-area: 1 / 1 / 2 / 2; }  .child-2 {   margin-left: 200px; }

See the Pen
CSS Stacking, Grid 2
by Sarah Drasner (@sdras)
on CodePen.

If you find this technique difficult to visualize, I’ve created a CSS Grid Generator that hopefully helps see things more clearly.


There are so many places to use these techniques! You can stack, layer and offset elements. You can make navigations, footers. You can create just about any type of layout where you want to have more fine-grain control of how elements are placed on a page.

The post How to Stack Elements in CSS appeared first on CSS-Tricks.

CSS-Tricks

,
[Top]

Techniques for a Newspaper Layout with CSS Grid and Border Lines Between Elements

I recently had to craft a newspaper-like design that featured multiple row and column spans with divider lines in between them. Take a look at the mockup graphic here and see if it makes you sweat at all. If you’re like me, you have been around a while and know just how difficult this would have been with old layout techniques.

Newspaper design with line dividers between cells

The project came with a few requirements:

  • Show the outlines of the grid
  • Columns can be wider, or longer than others
  • Divider lines must be shown between the various blocks

CSS Grid: Teaching an old layout new tricks

Newspaper layouts can cause headaches because everyday CSS is one-dimensional, meaning that elements flow on either a horizontal or vertical axis. Even modern flexbox layout is still uni-directional.

For a layout like this, we would almost want the properties that good ol’ HTML tables once provided: things like row and column spans to stretch cells in all directions. We would also want the benefits of modern day CSS, with all the responsiveness and flexible boxes that can grow to fill available space.

CSS grid combines the best of tables with the best of flexible boxes. In fact, grid’s even better because it provides the grid-gap property for creating gutters between cells while taking available space into account. Powerful as this may be, how can we create divider-lines exactly in the middle of those gutters?

Let’s look at three techniques to make that happen.

What we’ll create

First, we will build a simplified version of the newspaper design that’ll help illustrate the crux of the three different techniques that we’re going to cover. A deceptively easy design, one would say.

Column and row spans in a CSS grid layout

Technique 1: The faux column

This solution creates “faux” columns that allow us to draw vertical lines, and then place a grid on top. Horizontal dividers are painted if needed. The “faux” columns are created by using pseudo selectors in the grid container.

<div class="frontpage">   <div class="fp-cell fp-cell--1">     <div class="fp-item">1</div>   </div>   <div class="fp-cell fp-cell--2">     <div class="fp-item">2</div>   </div>   <div class="fp-cell fp-cell--3 fp-cell--border-top">     <div class="fp-item">3</div>   </div>   <div class="fp-cell fp-cell--4 fp-cell--border-top">     <div class="fp-item">4</div>   </div> </div>

See the Pen
Newspaper-design, ‘faux-column’ technique
by Marco Troost (@marco-troost)
on CodePen.

Setting up the lines between the columns

Let’s create a three-column container using display: grid and pseudo-selectors (:before and :after) to create two columns that fill 100% of the container’s height.

.frontpage {   position: relative;   display: grid;   /* Three columns */   grid-template-columns: 1fr 1fr 1fr;   grid-column-gap: 32px;   border: 1px solid transparent;   border-top: 1px solid #DADCE0;   border-bottom: 1px solid #DADCE0;   overflow: hidden; }  /* Two faux columns */ .frontpage:before, .frontpage:after {   position: absolute;   top: 0;   height: 100%;   content: '';   width: calc(33.3% - 4px); }  .frontpage:before {   left: 0;   border-right: 1px solid #DADCE0; }  .frontpage:after {   right: 0;   border-left: 1px solid #DADCE0; }

Note: 33% of the container doesn’t take the gutter width into account, so you’ll have to compensate accordingly.

This is calculated as:

33% minus (gutter-width divided by (amount of gutters times amount of gutters)) divided by amount of gutters)

Or, with actual numbers:

33% - (32 / (2* 2)) / 2 = 4

We could use one pseudo-selector instead:

.frontpage {   position: relative;   display: grid;   grid-template-columns: 1fr 1fr 1fr;   grid-column-gap: 32px;   border: 1px solid transparent;   border-top: 1px solid #DADCE0;   border-bottom: 1px solid #DADCE0;   overflow: hidden; }  .frontpage:before {   box-sizing: border-box;   position: absolute;   top: 0;   height: 100%;   content: '';   left: calc(33.3% - 5.3px);   width: calc(33.3% + 10.7px);   border-left: 1px solid #DADCE0;   border-right: 1px solid #DADCE0; }

See the Pen
Newsgrid-layout ‘faux-columns’ (using only :before)
by Marco Troost (@marco-troost)
on CodePen.

Note: A different calculation is needed when using only one pseudo-selector: One for positioning, and one for width.

The width is calculated as:

33% plus (amount of gutters times gutter-width) / (amount of gutters times amount of columns)

Again, with actual numbers:

33% + (2 * 32) / (2 * 3) = 10.7

The position is calculated as:

33% minus (amount of gutters times gutter-width) / (amount of gutters times amount of columns) divided by 2)

Making the grid

The design consists of four blocks of content. We’re going to place them in the container and give them a modifier class for future reference while making sure their z-index is higher than the pseudo-selectors of the grid.

<div class="frontpage">   <div class="fp-cell fp-cell--1"></div>   <div class="fp-cell fp-cell--2"></div>   <div class="fp-cell fp-cell--3"></div>   <div class="fp-cell fp-cell--4"></div> </div>

Now let’s set the background color for the cells (.fp-cell) to white. This way, the vertical lines won’t show through. We can also set the vertical padding for the cell to 16px in order to match half of the gutter.

The first and second content blocks should get their own unique spans as shown in the design. The first block spans all the way down and the second block spans the second and third columns.

.fp-cell {   position: relative;   z-index: 2;   padding: 16px 0;   background-color: #fff; }  /* Span all the way down! */ .fp-cell--1 {   grid-row: 1 / span 2; }  /* Span the second and third columns */ .fp-cell--2 {   grid-column: 2 / span 2; }

Vertical line dividers

If you look at the design, only the last two cells need a horizontal border. We can give ’em a sweet modifier class.

<div class="frontpage">   <div class="fp-cell fp-cell--1"></div>   <div class="fp-cell fp-cell--2"></div>   <div class="fp-cell fp-cell--3 fp-cell--border-top"></div>   <div class="fp-cell fp-cell--4 fp-cell--border-top"></div> </div>
.fp-cell--border-top:before {   content: '';   position: absolute;   top: 0;   left: -16px;   right: -16px;   border-top: 1px solid #DADCE0; }

The negative margins are half of the gutter width.

Technique #2: Using background-color

Another way to create the dividers is to utilize the grid-gap property. This solution doesn’t necessarily create a “real” distance between cells, but rather leaves some blank space where the background-color of the grid can shine through. The gutter width is delegated to padding within the grid cells.

<div class="container">   <div class="frontpage">     <div class="fp-cell fp-cell--1">       <div class="fp-item">1</div>     </div>     <div class="fp-cell fp-cell--2">       <div class="fp-item">2</div>     </div>     <div class="fp-cell fp-cell--3">       <div class="fp-item">3</div>     </div>     <div class="fp-cell fp-cell--4">       <div class="fp-item">4</div>     </div>   </div> </div>
.container {   overflow-x: hidden;   border-top: 1px solid #DADCE0;   border-bottom: 1px solid #DADCE0; }  .frontpage {   position: relative;   display: grid;   grid-template-columns: 1fr 1fr 1fr;   grid-gap: 1px;   margin: 0 -16px;   background-color: #DADCE0; }  .fp-cell {   background-color: #fff;   padding: 16px; }  .fp-cell--1 {   grid-row: 1 / span 2; }  .fp-cell--2 {   grid-column: 2 / span 2; }  .fp-cell--3 {   grid-column: 2; }  .fp-item {   background-color: #efefef;   display: flex;   align-items: center;   justify-content: center;   min-height: 200px;   height: 100%; }

See the Pen
Newspaper-design, background-color technique
by Marco Troost (@marco-troost)
on CodePen.

Since all cells have an extra 16px of horizontal padding, the grid needs to be offset by just as much. A wrapper container will take care of the overflow.

<div class="container">   <div class="frontpage">   <!-- ... -->   </div> </div>
.container {   border-top: 1px solid #DADCE0;   border-bottom: 1px solid #DADCE0;   overflow-x: hidden; }  .frontpage {   position: relative;   display: grid;   grid-template-columns: 1fr 1fr 1fr;   grid-gap: 1px;   background-color: #DADCE0;   margin: 0 -16px; }

Technique #3: Creating a cell border

This solution appends a right and bottom border to each cell. Like the last example, the grid-gap is mimicked by adding padding to the cell content. That means it also needs to be wrapped in an extra container.

<div class="container">   <div class="frontpage">     <div class="fp-cell fp-cell--1">       <div class="fp-item">1</div>     </div>     <div class="fp-cell fp-cell--2">       <div class="fp-item">2</div>     </div>     <div class="fp-cell fp-cell--3">         <div class="fp-item">3</div>     </div>     <div class="fp-cell fp-cell--4">       <div class="fp-item">4</div>     </div>   </div> </div>
.container {   border-top: 1px solid #DADCE0;   overflow-x: hidden; }  .frontpage {   margin: 0 -17px 0 -16px;   position: relative;   display: grid;   grid-template-columns: 1fr 1fr 1fr; }  .fp-cell {   padding: 16px;   background-color: #fff;   border-right: 1px solid #DADCE0;   border-bottom: 1px solid #DADCE0; }  .fp-cell--1 {   grid-row: 1 / span 2; }  .fp-cell--2 {   grid-column: 2 / span 2; }  .fp-cell--3 {   grid-column: 2; }  .fp-item {   background-color: #efefef;   display: flex;   align-items: center;   justify-content: center;   min-height: 200px;   height: 100%; }

See the Pen
Newspaper-design, ‘cell-border’-technique
by Marco Troost (@marco-troost)
on CodePen.

As mentioned, each cell is given a border on the right and on the bottom. The main trick here is the use of the (asymmetrical) negative margin on the grid. This is needed to compensate for the cell’s right border.

.frontpage {   margin: 0 -17px 0 -16px;   position: relative;   display: grid;   grid-template-columns: 1fr 1fr 1fr; }

Conclusion

Occam’s razor stipulates that the simplest solution wins. In our case, that’s technique number two. But then again, the other solutions have plenty of merit and they could prove useful if, for example, access to the DOM is not possible.

All of these techniques will work. Choosing the right one depends on your use case. The first technique uses the actual grid-gap property to create the gaps, but the others are perhaps easier to understand at a glance… and perhaps easier to maintain as well.

The post Techniques for a Newspaper Layout with CSS Grid and Border Lines Between Elements appeared first on CSS-Tricks.

CSS-Tricks

, , , , , , ,
[Top]

Oh Hey, Padding Percentage is Based on the Parent Element’s Width

I learned something about percentage-based (%) padding today that I had totally wrong in my head! I always thought that percentage padding was based on the element itself. So if an element is 1,000 pixels wide with padding-top: 50%, that padding is 500 pixels. It’s weird having top padding based on width, but that’s how it works — but only sorta. The 50% is based on the parent element’s width, not itself. That’s the part that confused me.

The only time I’ve ever messed with percentage padding is to do the aspect ratio boxes trick. The element is of fluid width, but you want to maintain an aspect ratio, hence the percentage padding trick. In that scenario, the width of the element is the width of the parent, so my incorrect mental model just never mattered.

It doesn’t take much to prove it:

See the Pen
% padding is based on parent, not itself
by Chris Coyier (@chriscoyier)
on CodePen.

Thanks to Cameron Clark for the email about this:

The difference is moot when you have a block element that expands to fill the width of its parent completely, as in every example used in this article. But when you set any width on the element other than 100%, this misunderstanding will lead to baffling results.

They pointed to this article by Aayush Arora who claims that only 1% of developers knew this.

The post Oh Hey, Padding Percentage is Based on the Parent Element’s Width appeared first on CSS-Tricks.

CSS-Tricks

, , , , ,
[Top]

A Little Reminder That Pseudo Elements are Children, Kinda.

Here’s a container with some child elements:

<div class="container">   <div>item</div>   <div>item</div>   <div>item</div> </div>

If I do:

.container::before {   content: "x" }

I’m essentially doing:

<div class="container">   [[[ ::before psuedo-element here ]]]   <div>item</div>   <div>item</div>   <div>item</div> </div>

Which will behave just like a child element mostly. One tricky thing is that no selector selects it other than the one you used to create it (or a similar selector that is literally a ::before or ::after that ends up in the same place).

To illustrate, say I set up that container to be a 2×2 grid and make each item a kind of pillbox design:

.container {   display: grid;   grid-template-columns: 1fr 1fr;   grid-gap: 0.5rem; }  .container > * {   background: darkgray;   border-radius: 4px;   padding: 0.5rem; }

Without the pseudo-element, that would be like this:

Six items in a clean two-by-two grid

If I add that pseudo-element selector as above, I’d get this:

Six items in a two-by-two grid, but with a seventh item at the beginning, pushing elements over by one

It makes sense, but it can also come as a surprise. Pseudo-elements are often decorative (they should pretty much only be decorative), so having it participate in a content grid just feels weird.

Notice that the .container > * selector didn’t pick it up and make it darkgray because you can’t select a pseudo-element that way. That’s another minor gotcha.

In my day-to-day, I find pseudo-elements are typically absolutely-positioned to do something decorative — so, if you had:

.container::before {   content: "";   position: absolute;   /* Do something decorative */ }

…you probably wouldn’t even notice. Technically, the pseudo-element is still a child, so it’s still in there doing its thing, but isn’t participating in the grid. This isn’t unique to CSS Grid either. For instance, you’ll find by using flexbox that your pseudo-element becomes a flex item. You’re free to float your pseudo-element or do any other sort of layout with it as well.

DevTools makes it fairly clear that it is in the DOM like a child element:

DevTools with a ::before element selected

There are a couple more gotchas!

One is :nth-child(). You’d think that if pseduo-elements are actually children, they would effect :nth-child() calculations, but they don’t. That means doing something like this:

.container > :nth-child(2) {   background: red; }

…is going to select the same element whether or not there is a ::before pseudo-element or not. The same is true for ::after and :nth-last-child and friends. That’s why I put “kinda” in the title. If pseudo-elements were exactly like child elements, they would affect these selectors.

Another gotcha is that you can’t select a pseudo-element in JavaScript like you could a regular child element. document.querySelector(".container::before"); is going to return null. If the reason you are trying to get your hands on the pseudo-element in JavaScript is to see its styles, you can do that with a little CSSOM magic:

const styles = window.getComputedStyle(   document.querySelector('.container'),   '::before' ); console.log(styles.content); // "x" console.log(styles.color); // rgb(255, 0, 0) console.log(styles.getPropertyValue('color'); // rgb(255, 0, 0)

Have you run into any gotchas with pseudo-elements?

The post A Little Reminder That Pseudo Elements are Children, Kinda. appeared first on CSS-Tricks.

CSS-Tricks

, , , , ,
[Top]

Web Standards Meet User-Land: Using CSS-in-JS to Style Custom Elements

The popularity of CSS-in-JS has mostly come from the React community, and indeed many CSS-in-JS libraries are React-specific. However, Emotion, the most popular library in terms of npm downloads, is framework agnostic.

Using the shadow DOM is common when creating custom elements, but there’s no requirement to do so. Not all use cases require that level of encapsulation. While it’s also possible to style custom elements with CSS in a regular stylesheet, we’re going to look at using Emotion.

We start with an install:

npm i emotion

Emotion offers the css function:

import {css} from 'emotion';

css is a tagged template literal. It accepts standard CSS syntax but adds support for Sass-style nesting.

const buttonStyles = css`   color: white;   font-size: 16px;   background-color: blue;    &:hover {     background-color: purple;   } `

Once some styles have been defined, they need to be applied. Working with custom elements can be somewhat cumbersome. Libraries — like Stencil and LitElement — compile to web components, but offer a friendlier API than what we’d get right out of the box.

So, we’re going to define styles with Emotion and take advantage of both Stencil and LitElement to make working with web components a little easier.

Applying styles for Stencil

Stencil makes use of the bleeding-edge JavaScript decorators feature. An @Component decorator is used to provide metadata about the component. By default, Stencil won’t use shadow DOM, but I like to be explicit by setting shadow: false inside the @Component decorator:

@Component({   tag: 'fancy-button',   shadow: false })

Stencil uses JSX, so the styles are applied with a curly bracket ({}) syntax:

export class Button {   render() {     return <div><button class={buttonStyles}><slot/></button></div>   } }

Here’s how a simple example component would look in Stencil:

import { css, injectGlobal } from 'emotion'; import {Component} from '@stencil/core';  const buttonStyles = css`   color: white;   font-size: 16px;   background-color: blue;   &:hover {     background-color: purple;   } ` @Component({   tag: 'fancy-button',   shadow: false }) export class Button {   render() {     return <div><button class={buttonStyles}><slot/></button></div>   } }

Applying styles for LitElement

LitElement, on the other hand, use shadow DOM by default. When creating a custom element with LitElement, the LitElement class is extended. LitElement has a createRenderRoot() method, which creates and opens a shadow DOM:

createRenderRoot()  {   return this.attachShadow({mode: 'open'}); }

Don’t want to make use of shadow DOM? That requires re-implementing this method inside the component class:

class Button extends LitElement {   createRenderRoot() {       return this;   } }

Inside the render function, we can reference the styles we defined using a template literal:

render() {   return html`<button class=$ {buttonStyles}>hello world!</button>` }

It’s worth noting that when using LitElement, we can only use a slot element when also using shadow DOM (Stencil does not have this problem).

Put together, we end up with:

import {LitElement, html} from 'lit-element'; import {css, injectGlobal} from 'emotion'; const buttonStyles = css`   color: white;   font-size: 16px;   background-color: blue;   &:hover {     background-color: purple;   } `  class Button extends LitElement {   createRenderRoot() {     return this;   }   render() {     return html`<button class=$ {buttonStyles}>hello world!</button>`   } }  customElements.define('fancy-button', Button);

Understanding Emotion

We don’t have to stress over naming our button — a random class name will be generated by Emotion.

We could make use of CSS nesting and attach a class only to a parent element. Alternatively, we can define styles as separate tagged template literals:

const styles = {   heading: css`     font-size: 24px;   `,   para: css`     color: pink;   ` } 

And then apply them separately to different HTML elements (this example uses JSX):

render() {   return <div>     <h2 class={styles.heading}>lorem ipsum</h2>     <p class={styles.para}>lorem ipsum</p>   </div> }

Styling the container

So far, we’ve styled the inner contents of the custom element. To style the container itself, we need another import from Emotion.

import {css, injectGlobal} from 'emotion';

injectGlobal injects styles into the “global scope” (like writing regular CSS in a traditional stylesheet — rather than generating a random class name). Custom elements are display: inline by default (a somewhat odd decision from spec authors). In almost all cases, I change this default with a style applied to all instances of the component. Below are the buttonStyles which is how we can change that up, making use of injectGlobal:

injectGlobal` fancy-button {   display: block; } `

Why not just use shadow DOM?

If a component could end up in any codebase, then shadow DOM may well be a good option. It’s ideal for third party widgets — any CSS that’s applied to the page simply won’t break the the component, thanks to the isolated nature of shadow DOM. That’s why it’s used by Twitter embeds, to take one example. However, the vast majority of us make components for for a particular site or app and nowhere else. In that situation, shadow DOM can arguably add complexity with limited benefit.

The post Web Standards Meet User-Land: Using CSS-in-JS to Style Custom Elements appeared first on CSS-Tricks.

CSS-Tricks

, , , , , , ,
[Top]