emGee Software Solutions Custom Database Applications

Share this

Web Technologies

Front-end development is not a problem to be solved

CSS-Tricks - Tue, 11/27/2018 - 07:16

HTML and CSS are often seen as a burden.

This is a feeling I’ve noticed from engineers and designers I’ve worked with in the past, and it’s a sentiment that’s a lot more transparent with the broader web community at large. You can hear it in Medium posts and on indie blogs, whether in conversations about CSS, web performance, or design tools.

The sentiment is that front-end development is a problem to be solved: “if we just have the right tools and frameworks, then we might never have to write another line of HTML or CSS ever again!” And oh boy what a dream that would be, right?

Well, no, actually. I certainly don’t think that front-end development is a problem at all.

What's behind this feeling? Well, designers want tools that let them draw pictures and export a batch of CSS and HTML files like Dreamweaver promised back in the day. On the other end, engineers don’t want to sweat accessibility, web performance or focus states among many, many other things. There’s simply too many edge cases, too many devices, and too many browsers to worry about. The work is just too much.

Consequently, I empathize with these feelings as a designer/developer myself, but I can’t help but get a little upset when I read about someone's relationship with Bootstrap or design systems, frameworks or CSS-in-JS solutions — and even design tools like Sketch or Figma. It appears that we treat front-end development as a burden, or something we want to void altogether by abstracting it with layers of tools.

We should see front-end development as a unique skillset that is critical to the success of any project.

I believe that’s why frameworks and tools like Bootstrap are so popular; not necessarily because they’re a collection of helpful components, but a global solution that corrects an inherent issue. And when I begin to see “Bootstrap” in multiple resumés for front-end applications, I immediately assume that we're going to be at odds with our approaches to design and development.

Bootstrap isn’t a skill though — front-end development is.

And this isn’t me just being a curmudgeon... I hope. I genuinely want tools that help us make better decisions, that help us build accessible, faster, and more beautiful websites in a way that pushes the web forward. That said, I believe the communities built up around these tools encourage designing and developing in a way that's ignorant of front-end skills and standards.

What’s the point in learning about vanilla HTML, CSS and JavaScript if they wind up becoming transpiled by other tools and languages?

Don’t get me wrong — I don’t think there’s anything wrong with Bootstrap, or CSS-in-JS, or CSS Modules, or fancy design tools. But building our careers around the limitations of these tools is a minor tragedy. Front-end development is complex because design is complex. Transpiling our spoken language into HTML and CSS requires vim and nuance, and always will. That’s not going to be resolved by a tool but by diligent work over a long period of time.

I reckon HTML and CSS deserve better than to be processed, compiled, and spat out into the browser, whether that’s through some build process, app export, or gigantic framework library of stuff that we half understand. HTML and CSS are two languages that deserve our care and attention to detail. Writing them is a skill.

I know I’m standing on a metaphorical soapbox here, and perhaps I’m being a tad melodramatic, but front-end development is not a problem to be solved. It’s a cornerstone of the web, and it’s not going away any time soon.

Is it?

The post Front-end development is not a problem to be solved appeared first on CSS-Tricks.

Categories: Web Technologies

FUIF: Responsive Images by Design

CSS-Tricks - Tue, 11/27/2018 - 07:11

Jon Sneyers:

One of the main motivations for FUIF is to have an image format that is responsive by design, which means it’s no longer necessary to produce many variants of the same image: low-quality placeholders, thumbnails, many downscaled versions for many display resolutions. A single file, truncated at different offsets, can do the same thing.

FLIF isn't anywhere near ready to use, but it's a fascinating idea. I love the idea that the format stores the image data in such a way that you request just first few kilobytes of the file and to essentially get a low-quality version, then you request more as needed. See this little demo from Eric Portis that shows it off somewhat via a Service Worker and a progressive JPG.

If this idea ever does get legs and support in browsers, Cloudinary is super well suited to take advantage of that, as they serve the best image format for the current browser — and that is massive for image performance.

Direct Link to ArticlePermalink

The post FUIF: Responsive Images by Design appeared first on CSS-Tricks.

Categories: Web Technologies

402 Payment Required - Evert Pot

Planet PHP - Tue, 11/27/2018 - 07:00

402 Payment Required is a status-code described by the standard as:

The 402 (Payment Required) status code is reserved for future use.

The original idea may have been that commercial websites and APIs would want to have a default way to communicate that a HTTP request can be repeated, after a user paid for service.

Usage

The RFC suggests that it’s not a good idea to use this status code today, because it may get a better definition in the future, possibly making existing sites incompatible with HTTP.

That being said, it hasn’t really stopped people from using the code anyway.

So should you use it? The RFC says no. But, I also don’t think there’s a major risk in doing so.

References
Categories: Web Technologies

Interview with Rob Allen - Voices of the ElePHPant

Planet PHP - Tue, 11/27/2018 - 05:08
Video

@akrabat

Audio Show Notes This episode sponsored by:

The post Interview with Rob Allen appeared first on Voices of the ElePHPant.

Categories: Web Technologies

Interview with Rob Allen - Voices of the ElePHPant

Planet PHP - Tue, 11/27/2018 - 05:08
Video

@akrabat

Audio Show Notes This episode sponsored by:

The post Interview with Rob Allen appeared first on Voices of the ElePHPant.

Categories: Web Technologies

CSS Grid in IE: Duplicate area names now supported!

CSS-Tricks - Mon, 11/26/2018 - 07:06

Autoprefixer is now up to version 9.3.1 and there have been a lot of updates since I wrote the original three-part CSS Grid in IE series — the most important update of which is the new grid-areas system. This is mostly thanks to Bogdan Dolin, who has been working like crazy to fix loads of Autoprefixer issues. Autoprefixer’s grid translations were powerful before, but they have gotten far more powerful now!

Article Series:
  1. Debunking common IE Grid misconceptions
  2. CSS Grid and the new Autoprefixer
  3. Faking an auto-placement grid with gaps
  4. Duplicate area names now supported! (This Post)
How Autoprefixer supports duplicate area names

In Part 2 of the series, I pointed out why Autoprefixer wasn’t able to handle duplicate area names that were used across multiple selectors.

To summarize, this is the example I gave in the article:

.grid-alpha { grid-template-areas: "delta echo"; } .grid-beta { grid-template-areas: "echo delta"; } .grid-cell { /* What column does .grid-cell go in? */ -ms-grid-column: ???; grid-area: echo; }

We thought that since Autoprefixer didn’t have access to the DOM, there was no way of knowing what grid the grid cell belonged to and thus which column the grid cell should go in.

However, I realized something. Grid cells are only ever affected by their direct parent element (ignoring display: contents). That meant that if the grid cell exists, it will always be a direct child of the grid template element. This gave me an idea for how we can solve the grid-area name conflict! 😁

.grid-alpha { grid-template-areas: "delta echo"; } .grid-beta { /* Uh oh, duplicate area names! */ grid-template-areas: "echo delta"; } .grid-cell { /* We will use the first occurrence by default */ -ms-grid-column: 2; grid-area: echo; } /* We have detected a conflict! Prefix the class with the parent selector. */ .grid-beta > .grid-cell { /* NO MORE CONFLICT! */ -ms-grid-column: 1; }

The entire grid-areas system needed to be re-written to achieve this, but it was totally worth the effort.

The way this new system works is that .grid-cell will default to using the first grid-template-areas property that it comes across. When it hits a conflicting grid template, it will create a new rule placing the parent selector in front of the child selector like so:

[full parent selector] > [direct child selector]

This is what we know purely from looking at the CSS and knowing how CSS Grid works:

  • A grid cell must be a direct descendant of the parent grid container for CSS Grid to work (assuming display: contents isn’t used).
  • grid-beta > .grid-cell will only work on .grid-cell elements that have been placed directly inside a .grid-beta element.
  • .grid-beta > .grid-cell will have no effect on .grid-cell elements placed directly inside .grid-alpha elements.
  • .grid-beta > .grid-cell will have no effect on .grid-cell elements nested deeply inside .grid-beta elements.
  • .grid-beta > .grid-cell will override the styling of the lonely .grid-cell CSS rule both because of rule order and specificity.

Because of those reasons, Autoprefixer can pretty safely resolve these conflicts without having any access to the DOM.

That last point in the list can be a little bit dangerous. It increases specificity which means that it may cause some IE styles to override others in a way that is different from how modern overrides are working. Since the generated rules only hold IE-specific grid styles, and they only apply under very specific circumstances, this is unlikely to cause an issue in 99.999% of circumstances. There is still potential for edge cases though.

If you ever find yourself needing to increase the specificity of the grid cell selector, here’s how to go about it.

Instead of writing this:

.grid { grid-template-areas: "area-name"; } .grid-cell { grid-area: area-name; }

...we write the rule like this:

.grid { grid-template-areas: "area-name"; } .grid > .grid-cell { grid-area: area-name; }

Autoprefixer will retain the selector and output something like this:

.grid { grid-template-areas: "area-name"; } .grid > .grid-cell { -ms-grid-column: 1; -ms-grid-row: 1; grid-area: area-name; } The exciting new possibilities!

So why is duplicate area name support so exciting?

Well, for one, it was just plain annoying when accidentally using a duplicate area name in older versions of Autoprefixer. It would break in IE and, in older versions of Autoprefixer, it would fail silently.

The main reason it is exciting though is that it opens up a whole new world of IE-friendly CSS Grid possibilities!

Use modifier classes to adjust a grid template

This was the use case that really made me want to get duplicate area name support into Autoprefixer. Think about this. You have a typical site with a header, a footer, a main area, and a sidebar down either side.

See the Pen Basic website layout by Daniel Tonon (@daniel-tonon) on CodePen.

Sometimes we want both sidebars, sometimes we want one sidebar, and sometimes we want no sidebars. This was very difficult to manage back when Autoprefixer didn’t support duplicate area names since we couldn't share area names across multiple grid templates. We would have to do something like this for it to work:

/* Before Duplicate area names were supported - n = no side-bars - f = first sidebar only - s = second sidebar only - fs = first and second sidebars */ .main-area { display: grid; grid-template: "content-n" / 1fr; } .main-area.has-first-sidebar { grid-template: "first-sb-f content-f" / 300px 1fr; } .main-area.has-second-sidebar { grid-template: "content-s second-sb-s" / 1fr 300px; } .main-area.has-first-sidebar.has-second-sidebar { grid-template: "first-sb-fs content-fs second-sb-fs" / 200px 1fr 200px; } .main-area > .content { grid-area: content-n; /* no side-bars */ } .main-area > .sidebar.first { grid-area: first-sb-f; /* first sidebar only */ } .main-area > .sidebar.second { grid-area: second-sb-s; /* second sidebar only */ } .main-area.has-first-sidebar > .content { grid-area: content-f; /* first sidebar only */ } .main-area.has-second-sidebar > .content { grid-area: content-s; /* second sidebar only */ } .main-area.has-first-sidebar.has-second-sidebar > .content { grid-area: content-fs; /* first and second sidebars */ } .main-area.has-first-sidebar.has-second-sidebar > .sidebar.first { grid-area: first-sb-fs; /* first and second sidebars */ } .main-area.has-first-sidebar.has-second-sidebar > .sidebar.second { grid-area: second-sb-fs; /* first and second sidebars */ } Autoprefixer translation /* Before Duplicate area names were supported - n = no sidebars - f = first sidebar only - s = second sidebar only - fs = first and second sidebars */ .main-area { display: -ms-grid; display: grid; -ms-grid-rows: auto; -ms-grid-columns: 1fr; grid-template: "content-n" / 1fr; } .main-area.has-first-sidebar { -ms-grid-rows: auto; -ms-grid-columns: 300px 1fr; grid-template: "first-sb-f content-f" / 300px 1fr; } .main-area.has-second-sidebar { -ms-grid-rows: auto; -ms-grid-columns: 1fr 300px; grid-template: "content-s second-sb-s" / 1fr 300px; } .main-area.has-first-sidebar.has-second-sidebar { -ms-grid-rows: auto; -ms-grid-columns: 200px 1fr 200px; grid-template: "first-sb-fs content-fs second-sb-fs" / 200px 1fr 200px; } .main-area > .content { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: content-n; /* no side-bars */ } .main-area > .sidebar.first { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: first-sb-f; /* first sidebar only */ } .main-area > .sidebar.second { -ms-grid-row: 1; -ms-grid-column: 2; grid-area: second-sb-s; /* second sidebar only */ } .main-area.has-first-sidebar > .content { -ms-grid-row: 1; -ms-grid-column: 2; grid-area: content-f; /* first sidebar only */ } .main-area.has-second-sidebar > .content { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: content-s; /* second sidebar only */ } .main-area.has-first-sidebar.has-second-sidebar > .content { -ms-grid-row: 1; -ms-grid-column: 2; grid-area: content-fs; /* first and second sidebars */ } .main-area.has-first-sidebar.has-second-sidebar > .sidebar.first { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: first-sb-fs; /* first and second sidebars */ } .main-area.has-first-sidebar.has-second-sidebar > .sidebar.second { -ms-grid-row: 1; -ms-grid-column: 3; grid-area: second-sb-fs; /* first and second sidebars */ }

🤢 Oh yeah, and don’t forget media queries! 🤮

That example was based off actual code that I had to write for an actual project… so yeah, I really wanted to get duplicate area name support into Autoprefixer.

Now that we do have duplicate area name support, we can simplify that code down to something much nicer 😊

/* Duplicate area names now supported! This code will work perfectly in IE with Autoprefixer 9.3.1 */ .main-area { display: grid; grid-template: "content" / 1fr; } .main-area.has-first-sidebar { grid-template: "first-sb content" / 300px 1fr; } .main-area.has-second-sidebar { grid-template: "content second-sb" / 1fr 300px; } .main-area.has-first-sidebar.has-second-sidebar { grid-template: "first-sb content second-sb" / 200px 1fr 200px; } .content { grid-area: content; } .sidebar.first { grid-area: first-sb; } .sidebar.second { grid-area: second-sb; } Autoprefixer translation .main-area { display: -ms-grid; display: grid; -ms-grid-rows: auto; -ms-grid-columns: 1fr; grid-template: "content" / 1fr; } .main-area.has-first-sidebar { -ms-grid-rows: auto; -ms-grid-columns: 300px 1fr; grid-template: "first-sb content" / 300px 1fr; } .main-area.has-second-sidebar { -ms-grid-rows: auto; -ms-grid-columns: 1fr 300px; grid-template: "content second-sb" / 1fr 300px; } .main-area.has-first-sidebar.has-second-sidebar { -ms-grid-rows: auto; -ms-grid-columns: 200px 1fr 200px; grid-template: "first-sb content second-sb" / 200px 1fr 200px; } .content { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: content; } .main-area.has-first-sidebar > .content { -ms-grid-row: 1; -ms-grid-column: 2; } .main-area.has-second-sidebar > .content { -ms-grid-row: 1; -ms-grid-column: 1; } .main-area.has-first-sidebar.has-second-sidebar > .content { -ms-grid-row: 1; -ms-grid-column: 2; } .sidebar.first { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: first-sb; } .main-area.has-first-sidebar.has-second-sidebar > .sidebar.first { -ms-grid-row: 1; -ms-grid-column: 1; } .sidebar.second { -ms-grid-row: 1; -ms-grid-column: 2; grid-area: second-sb; } .main-area.has-first-sidebar.has-second-sidebar > .sidebar.second { -ms-grid-row: 1; -ms-grid-column: 3; }

With that CSS, we are now able to use the has-first-sidebar and has-second-sidebar classes on the grid element to modify what grid template the browser uses. We no longer have to worry about defining exactly what grid grid cells are placed in.

Assign components reusable area names

One of the limitations of being forced to use unique area names was that components could not be given a single, consistent re-usable area name. We were forced to come up with unique area names for every grid.

Now that Autoprefixer has duplicate area name support, that limitation is gone. We can provide every component with a single area name that is based on their component name. We can then reference that one area name whenever we want to place that component inside a grid layout.

/* header.scss */ .header { grid-area: header; } /* nav.scss */ .nav { grid-area: nav; } /* sidebar.scss */ .sidebar { grid-area: sidebar; } /* content.scss */ .content { grid-area: content; } /* subscribe.scss */ .subscribe { grid-area: subscribe; } /* footer.scss */ .footer { grid-area: footer; } /* layout.scss */ .single-sidebar-layout { display: grid; grid-template-areas: "header header" "nav content" "subscribe content" "footer footer"; } .double-sidebar-layout { display: grid; grid-template-areas: "header header header" "nav content sidebar" "nav subscribe sidebar" "footer footer footer"; } Autoprefixer translation /* header.scss */ .header { -ms-grid-row: 1; -ms-grid-column: 1; -ms-grid-column-span: 2; grid-area: header; } .double-sidebar-layout > .header { -ms-grid-row: 1; -ms-grid-column: 1; -ms-grid-column-span: 3; } /* nav.scss */ .nav { -ms-grid-row: 2; -ms-grid-column: 1; grid-area: nav; } .double-sidebar-layout > .nav { -ms-grid-row: 2; -ms-grid-row-span: 2; -ms-grid-column: 1; } /* sidebar.scss */ .sidebar { -ms-grid-row: 2; -ms-grid-row-span: 2; -ms-grid-column: 3; grid-area: sidebar; } /* content.scss */ .content { -ms-grid-row: 2; -ms-grid-row-span: 2; -ms-grid-column: 2; grid-area: content; } .double-sidebar-layout > .content { -ms-grid-row: 2; -ms-grid-column: 2; } /* subscribe.scss */ .subscribe { -ms-grid-row: 3; -ms-grid-column: 1; grid-area: subscribe; } .double-sidebar-layout > .subscribe { -ms-grid-row: 3; -ms-grid-column: 2; } /* footer.scss */ .footer { -ms-grid-row: 4; -ms-grid-column: 1; -ms-grid-column-span: 2; grid-area: footer; } .double-sidebar-layout > .footer { -ms-grid-row: 4; -ms-grid-column: 1; -ms-grid-column-span: 3; } /* layout.scss */ .single-sidebar-layout { display: -ms-grid; display: grid; grid-template-areas: "header header" "nav content" "subscribe content" "footer footer"; } .double-sidebar-layout { display: -ms-grid; display: grid; grid-template-areas: "header header header" "nav content sidebar" "nav subscribe sidebar" "footer footer footer"; }

Here’s what we’ve got. Note that this should be viewed in IE.

See the Pen component-area-name technique by Daniel Tonon (@daniel-tonon) on CodePen.

Duplicate area name limitation

There is one fairly common use case that Autoprefixer still can’t handle at the moment. When the parent selector of the grid cell does not match up with the grid template selector, it tries to resolve a duplicate area name:

.grand-parent .mother { grid-template-areas: "child"; } .grand-parent .father { grid-template-areas: "child child"; } /* This will work */ .grand-parent .mother .child { grid-area: child; } /* This does not work because: - ".uncle" != ".grand-parent .mother" - ".uncle" != ".grand-parent .father" - "child" is a duplicate area name */ .uncle .child { grid-area: child; }

Here is a more realistic scenario of the current limitation in Autoprefixer’s algorithm:

.component .grid { display: grid; grid-template-areas: "one two"; grid-template-columns: 1fr 1fr; } /* This rule triggers duplicate area name conflicts. */ .component.modifier .grid { grid-template-areas: "one ... two"; grid-template-columns: 1fr 1fr 1fr; } /* This does not work because: - ".component" != ".component .grid" - ".component" != ".component.modifier .grid" - area names "one" and "two" both have duplicate area name conflicts */ .component .cell-one { grid-area: one; } .component .cell-two { grid-area: two; }

There are really only three ways of resolving this conflict at the moment.

Option 1: Remove the parent selector from child elements

Without any safeguards in place for scoping styles to a particular component, this is by far the most dangerous way to resolve the issue. I don’t recommend it.

.component .grid { display: grid; grid-template-areas: "one two"; grid-template-columns: 1fr 1fr; } .component.modifier .grid { grid-template-areas: "one ... two"; grid-template-columns: 1fr 1fr 1fr; } .cell-one { grid-area: one; } .cell-two { grid-area: two; } Autoprefixer translation .component .grid { display: -ms-grid; display: grid; grid-template-areas: "one two"; -ms-grid-columns: 1fr 1fr; grid-template-columns: 1fr 1fr; } .component.modifier .grid { grid-template-areas: "one ... two"; -ms-grid-columns: 1fr 1fr 1fr; grid-template-columns: 1fr 1fr 1fr; } .cell-one { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: one; } .component.modifier .grid > .cell-one { -ms-grid-row: 1; -ms-grid-column: 1; } .cell-two { -ms-grid-row: 1; -ms-grid-column: 2; grid-area: two; } .component.modifier .grid > .cell-two { -ms-grid-row: 1; -ms-grid-column: 3; } Option 2: Go back to using unique area names

This solution is pretty ugly, but if you have no control over the HTML, then this is probably the best way of handling the issue.

.component .grid { display: grid; grid-template-areas: "one two"; grid-template-columns: 1fr 1fr; } .component .cell-one { grid-area: one; } .component .cell-two { grid-area: two; } .component.modifier .grid { grid-template-areas: "modifier_one ... modifier_two"; grid-template-columns: 1fr 1fr 1fr; } .component.modifier .cell-one { grid-area: modifier_one; } .component.modifier .cell-two { grid-area: modifier_two; } Autoprefixer translation .component .grid { display: -ms-grid; display: grid; grid-template-areas: "one two"; -ms-grid-columns: 1fr 1fr; grid-template-columns: 1fr 1fr; } .component .cell-one { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: one; } .component .cell-two { -ms-grid-row: 1; -ms-grid-column: 2; grid-area: two; } .component.modifier .grid { grid-template-areas: "modifier_one ... modifier_two"; -ms-grid-columns: 1fr 1fr 1fr; grid-template-columns: 1fr 1fr 1fr; } .component.modifier .cell-one { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: modifier_one; } .component.modifier .cell-two { -ms-grid-row: 1; -ms-grid-column: 3; grid-area: modifier_two; } Option 3: Use a BEM-style naming convention

Yep, if you use the BEM naming convention (or something similar), this will practically never be an issue for you. This is easily the preferred way of dealing with the issue if it’s an option.

.component__grid { display: grid; grid-template-areas: "one two"; grid-template-columns: 1fr 1fr; } .component__grid--modifier { grid-template-areas: "one ... two"; grid-template-columns: 1fr 1fr 1fr; } .component__cell-one { grid-area: one; } .component__cell-two { grid-area: two; } Autoprefixer translation .component__grid { display: -ms-grid; display: grid; grid-template-areas: "one two"; -ms-grid-columns: 1fr 1fr; grid-template-columns: 1fr 1fr; } .component__grid--modifier { grid-template-areas: "one ... two"; -ms-grid-columns: 1fr 1fr 1fr; grid-template-columns: 1fr 1fr 1fr; } .component__cell-one { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: one; } .component__grid--modifier > .component__cell-one { -ms-grid-row: 1; -ms-grid-column: 1; } .component__cell-two { -ms-grid-row: 1; -ms-grid-column: 2; grid-area: two; } .component__grid--modifier > .component__cell-two { -ms-grid-row: 1; -ms-grid-column: 3; }

I have some issues with BEM, but with a few tweaks to the syntax, it can be a really great way to control CSS specificity and scoping.

Other Autoprefixer updates

While I’m here, I’ll give you an update on a couple of other developments that have occurred in Autoprefixer since I wrote the original CSS Grid in IE series.

Before we dive in though, here is how to set things up in CodePen in case you want to follow along with your own experiments.

Using Autoprefixer Grid translations in CodePen

CodePen has already upgraded to version 9.3.1 of Autoprefixer. You will now easily be able to integrate IE-friendly CSS Grid styles into your pens. First, make sure that Autoprefixer is enabled in the CodePen settings (Settings > CSS > [Vendor Prefixing] > Autoprefixer).

Step 1: Turn on Autoprefixer in CodePen

Then add the all new /* autoprefixer grid: on */ control comment to the top of the CSS Panel. I will dive into this awesome new feature a bit more later.

Step 2: Add the control comment

You can now write modern IE-friendly CSS Grid code and CodePen will automatically add in all of the IE prefixes for you.

"View compiled CSS" button The compiled CSS view

In order to actually test your pens in IE though, you will need to view the pen in "Debug Mode" (Change View > Debug Mode). The pen will need to be saved before you will have access to this view.

Enabling Debug Mode for testing in IE

If you’d like to try out a tool that shows you real-time Autoprefixer output, try the online tool just for that. Input CSS on the left. It will output Autoprefixer’s translated CSS on the right as you type.

autoprefixer.github.io New Autoprefixer control comments

We don’t always have the ability to alter the Autoprefixer configuration settings. If you have ever tried to do some IE-friendly CSS Grid experiments in CodePen in the past, you will know the pain of not having direct access to the Autoprefixer settings. There are also some frameworks like Create React App and Angular that don’t allow users to alter the Autoprefixer settings. There was also a bit of a skill barrier that prevented some users from using Grid because they were unsure of how to enable Grid translations.

This limitation was causing pain for many users but then Andrey Alexandrov submitted a pull request that introduced a new control comment. This new control comment gave users the ability to easily turn grid translations on and off from inside the CSS file. This was far easier than doing it through configuration settings. It was also accessible to all users no matter how they compile their CSS.

Adding /* autoprefixer grid: on */ will enable grid translations for that entire block while /* autoprefixer grid: off */ will disable grid translations for that block. Only the first grid control comment in a block will be applied.

/* Globally enable grid prefixes */ /* autoprefixer grid: on */ .grid { display: grid; } .non-ie .grid { /* Turn off grid prefixes but only for this block */ /* autoprefixer grid: off */ display: grid; /* Grid control comments affect the whole block. This control comment is ignored */ /* autoprefixer grid: on */ grid-column: 1; }

The above code translates into the following (I’ve filtered out the explanation comments):

/* autoprefixer grid: on */ .grid { display: -ms-grid; display: grid; } .non-ie .grid { /* autoprefixer grid: off */ display: grid; /* autoprefixer grid: on */ grid-column: 1; } @supports can disable grid translations

The new control comments aren’t the only way to selectively prevent Autoprefixer from outputting grid translation code.

Autoprefixer will never be able to support implicit grid auto-placement. If you use an @supports statement that checks for something like grid-auto-rows: 0, Autoprefixer will not output Grid translations for code entered inside that statement.

.prefixed .grid { display: -ms-grid; display: grid; } /* Checking grid-auto-* support prevents prefixes */ @supports (grid-auto-rows: 0) { .modern .grid { display: grid; } } /* Checking basic grid support still outputs prefixes */ @supports (display: grid) { .still-prefixed .grid { display: -ms-grid; display: grid; } }

To support IE, Autoprefixer can generate something like 50 lines of extra CSS sometimes. If you are writing Grid code inside an @supports statement, you will want IE translations to be turned off to reduce the weight of your CSS. If you don’t want to use @supports (grid-auto-rows: 0) then you can use a control comment inside the @supports statement instead.

@supports (display: grid) { .prefixed .grid { display: -ms-grid; display: grid; } } @supports (display: grid) { /* autoprefixer grid: off */ .modern .grid { display: grid; } } Autoprefixer now inherits grid-gaps

In the original article series, I said that Autoprefixer was unable to inherit grid-gap values. In version 9.1.1, grid-gap values were able to inherit through media queries. In version 9.3.1, they have become inheritable through more specific selectors as well.

.grid { display: grid; grid-gap: 20px; /* grid-gap is stated here */ grid-template: "one two" / 1fr 1fr; } @media (max-width: 600px) { .grid { /* grid-gap is now inhereited here */ grid-template: "one" "two" / 1fr; } } .grid.modifier { /* grid-gap is now inhereited here as well */ grid-template: "one" "two" / 1fr; } .one { grid-area: one; } .two { grid-area: two; } Autoprefixer translation .grid { display: -ms-grid; display: grid; grid-gap: 20px; /* grid-gap is stated here */ -ms-grid-rows: auto; -ms-grid-columns: 1fr 20px 1fr; grid-template: "one two" / 1fr 1fr; } @media (max-width: 600px) { .grid { /* grid-gap is now inhereited here */ -ms-grid-rows: auto 20px auto; -ms-grid-columns: 1fr; grid-template: "one" "two" / 1fr; } } .grid.modifier { /* grid-gap is now inherited here as well */ -ms-grid-rows: auto 20px auto; -ms-grid-columns: 1fr; grid-template: "one" "two" / 1fr; } .one { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: one; } .grid.modifier > .one { -ms-grid-row: 1; -ms-grid-column: 1; } .two { -ms-grid-row: 1; -ms-grid-column: 3; grid-area: two; } .grid.modifier > .two { -ms-grid-row: 3; -ms-grid-column: 1; } @media (max-width: 600px) { .one { -ms-grid-row: 1; -ms-grid-column: 1; } .two { -ms-grid-row: 3; -ms-grid-column: 1; } } grid-template: span X; now works

In Part 2 this series, I mentioned that the following syntax doesn’t work:

.grid-cell { grid-column: span 2; }

This was fixed in version 9.1.1. It now translates into the following:

.grid-cell { -ms-grid-column-span: 2; grid-column: span 2; } New warning for mixing manual and area based placement

We had a user complain that Autoprefixer wasn’t handling grid areas correctly. Upon further investigation, we realized that they were applying both a grid-area and a grid-column setting within the same CSS rule.

.grid { display: grid; grid-template-areas: "a b"; } /* This doesn't work very well */ .grid-cell { grid-column: 2; grid-area: a; }

Either use grid-area on its own, or us grid-column & grid-row. Never use both at the same time.

If you are curious, this is what Autoprefixer outputs for the above code:

.grid { display: -ms-grid; display: grid; grid-template-areas: "a b"; } /* This doesn't work very well */ .grid-cell { -ms-grid-row: 1; -ms-grid-column: 1; -ms-grid-column: 2; grid-column: 2; grid-area: a; }

There is one exception to this. You may need a grid cell to overlap other grid cells in your design. You want to use grid-template-areas for placing your grid cells due to how much easier Autoprefixer makes the overall cell placement. You can't really create cell overlaps using grid-template-areas though. To create this overlap, you can use grid-[column/row]-end: span X; after the grid-area declaration to force the overlap.

.grid { display: grid; grid-template-areas: "a . ." "a b b" "a . ."; grid-template-columns: 1fr 1fr 1fr; grid-template-rows: 1fr 1fr 1fr; } .grid-cell-a { grid-area: a; /* place cell span after the grid-area to force an overlap */ grid-column-end: span 2; }

See the Pen column-span + grid-area experiment by Daniel Tonon (@daniel-tonon) on CodePen.

However if you have declared grid gaps in your grid, you will need to write the column/row span prefix manually while taking the extra columns/rows generated by Autoprefixer into consideration (IE doesn't support grid-gap). There is an issue for this on GitHub.

.grid { display: grid; grid-template-areas: "a . ." "a b c" "a . ."; grid-template-columns: 1fr 1fr 1fr; grid-template-rows: 1fr 1fr 1fr; grid-gap: 10px; } .grid-cell-a { grid-area: a; /* IE column span added manually */ -ms-grid-column-span: 3; /* IE spans 2 columns + the gap */ grid-column-end: span 2; /* Modern browsers only span 2 columns */ }

See the Pen column-span + grid-area experiment 2 by Daniel Tonon (@daniel-tonon) on CodePen.

This technique currently produces a warning message in Autoprefixer that can't easily be hidden. An issue for this is on GitHub.

New warning when using [align/justify/place]-[content/items]

Unfortunately. IE does not have the ability to align grid cells from the parent container. The only way to align grid cells in IE is by using the -ms-grid-row-align and the -ms-grid-column-align properties. These translate to align-self and justify-self in modern day grid syntax.

The following properties will trigger a warning in Autoprefixer if used in conjunction with a CSS Grid property:

  • align-items
  • align-content
  • justify-items
  • justify-content
  • place-items
  • place-content

The align-content, justify-content and place-content properties are pretty much impossible to replicate in IE. The align-items, justify-items and place-items properties, on the other hand, are quite easy to replicate using their self equivalents on the child elements (place-self support was added in 9.3.0).

/* [align/justify/place]-items is *NOT* IE friendly */ .align-justify-items { display: grid; align-items: start; justify-items: end; } .place-items { display: grid; place-items: start end; } /*[align/justify/place]-self *IS* IE friendly */ .align-justify-grid { display: grid; } .align-justify-grid > * { align-self: start; justify-self: end; } .place-grid { display: grid; } .place-grid > * { place-self: start end; } Autoprefixer translation /* [align/justify/place]-items is *NOT* IE friendly */ .align-justify-items { display: -ms-grid; display: grid; align-items: start; justify-items: end; } .place-items { display: -ms-grid; display: grid; place-items: start end; } /*[align/justify/place]-self *IS* IE friendly */ .align-justify-grid { display: -ms-grid; display: grid; } .align-justify-grid > * { -ms-grid-row-align: start; align-self: start; -ms-grid-column-align: end; justify-self: end; } .place-grid { display: -ms-grid; display: grid; } .place-grid > * { -ms-grid-row-align: start; -ms-grid-column-align: end; place-self: start end; }

.grid { [align/justify/place]-items } and .grid > * { [align/justify/place]-self } are generally quite interchangeable with one another. This substitution doesn’t always work, but in most cases, the two methods tend to act in much the same way.

Below is a pen demonstrating the difference between the IE friendly alignment method and the IE unfriendly alignment method. In modern browsers they look identical, but in IE one looks the same as the modern browsers and one does not.

See the Pen place-items experiment by Daniel Tonon (@daniel-tonon) on CodePen.

That’s all, folks

I hope you have enjoyed reading about the awesome new improvements the Autoprefixer community has made to the project over the past few months. The new control comments make enabling and disabling grid translations an absolute breeze. The new grid-areas system is also exciting. I love all the new IE-friendly CSS Grid options that the new areas system opens up, and I think you will too. 🙂

Article Series:
  1. Debunking common IE Grid misconceptions
  2. CSS Grid and the new Autoprefixer
  3. Faking an auto-placement grid with gaps
  4. Duplicate area names now supported! (This Post)

The post CSS Grid in IE: Duplicate area names now supported! appeared first on CSS-Tricks.

Categories: Web Technologies

You might not need a loop

CSS-Tricks - Mon, 11/26/2018 - 07:02

Ire Aderinokun has written a nifty piece using loops and when we might consider replacing it with another method, say .map() and .filter(). I particularly like what she has to say here:

As I mentioned earlier, loops are a great tool for a lot of cases, and the existence of these new methods doesn't mean that loops shouldn't be used at all.

I think these methods are great because they provide code that is in a way self-documenting. When we use the filter() method instead of a for loop, it is easier to understand at first glance what the purpose of the logic is.

However, these methods have very specific use cases and may be overkill if their full value isn't being used. An example of this is the map() method, which can technically be used to replace almost any arbitrary loop. If in our first example, we only wanted to modify the original articles array and not create a new, modified, amazingArticles, using this method would be unnecessary. It's important to use the method that suits each scenario, to make sure that we aren't over- or under-performing.

If you’re interested in digging more into this subject, Adan Giese wrote a great post about the .filter() method a short while ago that’s definitely worth checking out. Oh, and speaking of lots of different ways to approach loops, Chris compiled a list of options for looping over querySelectorAll NodeLists where forEach is just one of many options.

Direct Link to ArticlePermalink

The post You might not need a loop appeared first on CSS-Tricks.

Categories: Web Technologies

Announcing API Problem 3.x for PHP, complete with PSR-17 support - larry@garfieldtech.com

Planet PHP - Sat, 11/24/2018 - 16:06
Announcing API Problem 3.x for PHP, complete with PSR-17 support

After a longer than intended delay, I'm happy to announce the 3.0 release of my Crell/ApiProblem library.

ApiProblem is a small, self-contained library for modeling IETF RFC 7807 "Problem Details" messages. (I know, more gibberish.) That is, it makes it easier for PHP developers to build a message for their API servers to handle cases where Something Bad Happened(tm).

Continue reading this post on SteemIt

Larry 24 November 2018 - 7:06pm
Categories: Web Technologies

The Current State of Styling Scrollbars

CSS-Tricks - Fri, 11/23/2018 - 07:41

If you need to style your scrollbars right now, one option is to use a collection of ::webkit prefixed CSS properties.

See the Pen CSS-Tricks Almanac: Scrollbars by Chris Coyier (@chriscoyier) on CodePen.

Sadly, that doesn't help out much for Firefox or Edge, or the ecosystem of browsers around those.

But if that's good enough for what you need, you can get rather classy with it:

See the Pen Custom Scrollbar styling by Devstreak (@devstreak) on CodePen.

There are loads of them on CodePen to browse. It's a nice thing to abstract with a Sass @mixin as well.

There is good news on this front! The standards bodies that be have moved toward a standardizing methods to style scrollbars, starting with the gutter (or width) of them. The main property will be scrollbar-gutter and Geoff has written it up here. Hopefully Autoprefixer will help us as the spec is finalized and browsers start to implement it so we can start writing the standardized version and get any prefixed versions from that.

But what if we need cross-browser support?

If styled scrollbars are a necessity (and I don't blame you), then you'll probably have to reach for a JavaScript solution. There must be dozens of libraries for that. I ran across simplebar and it looks like a pretty modern one with easy instantiation. Here's a demo of that:

See the Pen simple-bar by Chris Coyier (@chriscoyier) on CodePen.

Here's another one called simple-scrollbar:

See the Pen simple-scroll-bar by Chris Coyier (@chriscoyier) on CodePen.

Das Surma did a very fancy tutorial that creates a custom scrollbar that doesn't actually require any JavaScript when scrolling (good for perf), but does require some JavaScript setup code.

Custom scrollbars are extremely rare and that’s mostly due to the fact that scrollbars are one of the remaining bits on the web that are pretty much unstylable (I’m looking at you, date picker). You can use JavaScript to build your own, but that’s expensive, low fidelity and can feel laggy. In this article we will leverage some unconventional CSS matrices to build a custom scroller that doesn’t require any JavaScript while scrolling, just some setup code.

I'll embed a copy here:

See the Pen Custom Scrollbar Example from Google Chrome Labs by Chris Coyier (@chriscoyier) on CodePen.

The post The Current State of Styling Scrollbars appeared first on CSS-Tricks.

Categories: Web Technologies

Discovering the Shadow DOM

Echo JS - Fri, 11/23/2018 - 01:56
Categories: Web Technologies

Pages