Friday, 28 June 2019
Nownownow
Matthias Ott, relaying an idea he heard from Derek Sivers:
Many personal websites, including this one here, have an “about” page. It’s a page that tells you something about the background of a person or about the services provided. But what this page often doesn’t answer – and neither do Twitter or Facebook pages – is what this person really is up to at the moment. A page that answers questions like: What are you focused on at this point in your life? What have you just started working on that excites you like nothing else? Did you just move to a new town? Did you start a new career as a Jengascript wrangler? To answer all those questions, Derek suggests to create a “now page”. A page that tells visitors of your site “what you’d tell a friend you hadn’t seen in a year.”
Very cool idea! Derek has a directory page of people who have done this.
I have more scattered thoughts:
- It's funny how social media sites aren't very helpful with this. You'd think looking at someone's social media profile would be the quickest and easiest way to catch up with what they are doing right now, but it just ain't. That's true for me, too. Random statements of what you're working on don't make very good social media posts. Maybe a pinned tweet could be like a "now" page, though.
- I wonder if more homepages on people's personal sites should be this. As I browse around some of the sites, I like a lot of the "now" pages more than I like the homepage.
- I went with a "what I want you to do" section on my personal site. It's a different vibe, but it almost doubles as a "now" page, as the things I want you to do are fairly related to the things I'm doing. Maybe the idea of a do page has some legs.
Direct Link to Article — Permalink
The post Nownownow appeared first on CSS-Tricks.
from CSS-Tricks https://ift.tt/2ITPesW
via IFTTT
Thursday, 27 June 2019
Which CSS IS AWESOME makes the most sense if you don’t know CSS well?
Peter-Paul posted this question:
Which of the examples in the image do you consider correct?
If you know CSS well, don't reply, just retweet.
If you don't know CSS too well, please reply to the poll in the next tweet. pic.twitter.com/4bgnf9Wdkc
— ppk 🇪🇺 (@ppk) June 17, 2019
Note the interesting caveat: only vote in the poll if you don't know CSS well.
The winning answer was D! You gotta wonder if the result would have been different if the request for non-CSS experts wasn't there.
I like to think I know CSS OK, so I didn't vote. My brain goes like this:
- I think he's asking "by default," so the answer may assume there's no other CSS doing anything to that text.
- I wish I knew why the box was that particular width, but I guess I'll just assume it's a set
width
. - It's not B because ellipsis stuff requires extra stuff, and doesn't work on multiple lines like that — unless we're talking line clamping, which is even weirder.
- It's not C because that requires hiding overflow which is never really a default — that is, except off the top and left of the browser window, I guess. Or in an iframe.
- It's not D because words just don't break like that unless you do pretty specific stuff.
- A actually makes decent sense. It's weird to look at, but I've been dealing with stuff busting out of containers my whole career. C'est la vie.
Remember, we've done a deep dive into CSS IS AWESOME before and how it interestingly captures the weirdness of CSS.
The post Which CSS IS AWESOME makes the most sense if you don’t know CSS well? appeared first on CSS-Tricks.
from CSS-Tricks https://ift.tt/2Yh8Ooc
via IFTTT
Wednesday, 26 June 2019
5 reasons why you shouldn’t use logo-maker apps
Your logo is such an essential part of your business, you want to get the design right, right? Tempting as it might be to use an online logo maker, it is not advisable. Logo generator apps such as Wix or Canva might sound like the quickest and cheapest solution but quick and cheap are not necessarily better. Not when it comes to your logo. This is far too important. A generic design won’t represent your business in the same way that a bespoke logo can.
1. Not unique
With an online logo creator, you work with predesigned icons and symbols that are available to everyone. As a result, other businesses could create the same, or similar logo to yours. At TRCREATIVE, we specialise in logo design and creating a bespoke brand identity. We know that your logo must be unique and relevant. We work closely with our clients to create an original logo with high visual impact while communicating what their business is about.
2. Too generic
A logo generator takes a generic approach because it has to appeal to hundreds and thousands of businesses. Logos with broad appeal, available to everyone, lack that distinctive, creative design edge. TRCREATIVE creates logos that are noticeable and different. Our process explores colours, fonts, shapes and illustrations. This allows us to visualise and then shape a logo around your brand to make it stand out for all the right reasons.
3. Causes confusion
Just as you can’t write an original book by copying someone else’s words, you can’t create an original logo by using a logo generator with its off-the-shelf icons, symbols and colours. It is confusing for customers and potential customers if businesses with similar logos are in the same or similar market. You don’t want to mislead the customer. You want to build their trust and gain their respect. People are loyal to brands because they trust them.
4. Lacks creativity
The logo maker can’t ask questions. It doesn’t know your business. It can’t understand what your brand is about. TRCREATIVE gets to the heart of this. We incorporate your specific values and qualities into the logo design. We bring a level of thought and analysis to the design that you simply can’t get with a logo generator. We bring creative expression to the logo and create a unique story within the artwork. The result is a strong, distinctive piece of work that can be used for market communications to show consistency across your brand.
5. Copycat design
If you’ve used an online logo maker to create your logo, there’s nothing to stop another business generating a similar or identical one, especially if it quick and free to reproduce. The problem is, what’s to stop them from trading on your identity and reputation? To avoid this, the team at TRCREATIVE always turn each marque black and white and upload it to Google image search to ensure that it is unique. We can also work with you to register your new brand identity to protect it. Contact us today for more information. We work on logo design in Cheshire and our business is to help you create the right logo for your business.
from TRCREATIVE https://ift.tt/2LjK7Up
via IFTTT
Getting to Know the useReducer React Hook
useReducer
is one of a handful of React hooks that shipped in React 16.7.0. It accepts a reducer function with the application initial state, returns the current application state, then dispatches a function.
Here is an example of how it is used;
const [state, dispatch] = useReducer(reducer, initialState);
What’s the good for? Well, think about any situation where having the first loaded state of the application might be nice. Let’s say the starting point on an interactive map. Maybe it’s an app that lets the user build a custom car with custom options from a default model. Here’s a pretty neat demo of a calculator app that puts useRedcuer
to use in order to reset the calculator to a default state of zero when clearing it out.
See the Pen
Basic React Hook Calculator by Gianpierangelo De Palma (@dpgian)
on CodePen.
We’re going to dig into a couple more examples in this post, but let’s first look at the hook itself to get a better idea of what it is and what exactly it does when it’s used.
The almighty reducer
It’s tough to talk about useState
without also mentioning JavaScript’s reduce
method. We linked it up at the very top, but Sarah’s post is an excellent overview of reducers and helps set the state for where we’re going here.
The first and most important thing to understand about a reducer is that it will always only return one value. The job of a reducer is to reduce. That one value can be a number, a string, an array or an object, but it will always only be one. Reducers are really great for a lot of things, but they're especially useful for applying a bit of logic to a group of values and ending up with another single result.
So, if we have an array of numbers, reduce
will distill it down to a single number that adds up for as many times as there are values. Say we have this simple array:
const numbers = [1, 2, 3]
...and we have a function that logs each time our reducer makes a calculation into the console. This will help us see how reduce
distills the array into a single number.
const reducer = function (tally, number) {
console.log(`Tally: ${tally}, Next number: ${number}, New Total: ${tally + number}`)
return tally + number
}
Now let’s run a reducer on it. As we saw earlier, reduce
takes dispatches a function that runs against a default state. Let’s plug our reducer
function and an initial value of zero in there.
const total = numbers.reduce(reducer, 0)
Here’s what gets logged to the console:
"Tally: 0, Next number: 1, New Total: 1"
"Tally: 1, Next number: 2, New Total: 3"
"Tally: 3, Next number: 3, New Total: 6"
See how reduce
takes an initial value and builds on it as each number in the array is added to it until we get a final value? In this case, that final value is 6.
I also really like this (modified) example from Dave Ceddia that shows how reduce
can be used on an array of letters to spell a word:
var letters = ['r', 'e', 'd', 'u', 'c', 'e'];
// `reduce` takes 2 arguments:
// - a function to do the reducing (you might say, a "reducer")
// - an initial value for accumulatedResult
var word = letters.reduce(
function(accumulatedResult, arrayItem) {
return accumulatedResult + arrayItem;
},
''); // <-- notice this empty string argument: it's the initial value
console.log(word) // => "reduce"
useReducer works with states and actions
OK, that was a lot of refresher to get what we’re really talking about: userReducer
. It’s important to get all this, though, because you may have noticed where we’re going now after having seen the way reduce
fires a function against an initial value. It’s the same sort of concept, but returns two elements as an array, the current state and a dispatch function.
In other words:
const [state, dispatch] = useReducer(reducer, initialArg, init);
What’s up with that third init
argument? It’s an optional value that will lazily create the initial state. That means we can calculate the initial state/value with an init
function outside of the reducer instead of providing an explicit value. That’s handy if the initial value could be different, say based on a last saved state instead of a consistent value.
To get it working, we need to do a few things:
- Define an initial state.
- Provide a function that contains actions that update the state.
- Trigger
userReducer
to dispatch an updated state that’s calculated relative to the initial state.
The classic example of this a counter application. In fact, that’s what React’s docs use to drive the concept home. Here’s that put into practice:
See the Pen
React useReducer 1 by Kingsley Silas Chijioke (@kinsomicrote)
on CodePen.
It’s a good example because it demonstrates how an initial state (a zero value) is used to calculate a new value each time an action is fired by clicking either the increase or decrease button. We could even throw in a “Reset" button in there to clear the total back to the initial state of zero.
Example: A Car Customizer
See the Pen
React useReducer - car example by Geoff Graham (@geoffgraham)
on CodePen.
In this example, we are making the assumption that the user has selected a car to purchase. However, we want the app to allow the user to add extra options to the car. Each option has a price that adds to the base total.
First, we need to create the initial state which will consist of the car, an empty array to keep track of features, and an additional price that starts at $26,395 and a list of items in the store, so the user can pick what they want.
const initialState = {
additionalPrice: 0,
car: {
price: 26395,
name: "2019 Ford Mustang",
image: "https://cdn.motor1.com/images/mgl/0AN2V/s1/2019-ford-mustang-bullitt.jpg",
features: []
},
store: [
{ id: 1, name: "V-6 engine", price: 1500 },
{ id: 2, name: "Racing detail package", price: 1500 },
{ id: 3, name: "Premium sound system", price: 500 },
{ id: 4, name: "Rear spoiler", price: 250 }
]
};
Our reducer function will handle two things: the addition and removal of new items.
const reducer = (state, action) => {
switch (action.type) {
case "REMOVE_ITEM":
return {
...state,
additionalPrice: state.additionalPrice - action.item.price,
car: { ...state.car, features: state.car.features.filter((x) => x.id !== action.item.id)},
store: [...state.store, action.item]
};
case "BUY_ITEM":
return {
...state,
additionalPrice: state.additionalPrice + action.item.price,
car: { ...state.car, features: [...state.car.features, action.item] },
store: state.store.filter((x) => x.id !== action.item.id)
}
default:
return state;
}
}
When the user selects the item she wants, we update the features
for the car, increase the additionalPrice
and also remove the item from the store. We ensure that the other parts of the state remain as they are.
We do something similar when a user removes an item from the features list - reduce the additional price, return the item to the store.
Here is how the App component looks like.
const App = () => {
const inputRef = useRef();
const [state, dispatch] = useReducer(reducer, initialState);
const removeFeature = (item) => {
dispatch({ type: 'REMOVE_ITEM', item });
}
const buyItem = (item) => {
dispatch({ type: 'BUY_ITEM', item })
}
return (
<div>
<div className="box">
<figure className="image is-128x128">
<img src={state.car.image} />
</figure>
<h2>{state.car.name}</h2>
<p>Amount: ${state.car.price}</p>
<div className="content">
<h6>Extra items you bought:</h6>
{state.car.features.length ?
(
<ol type="1">
{state.car.features.map((item) => (
<li key={item.id}>
<button
onClick={() => removeFeature(item)}
className="button">X
</button>
{item.name}
</li>
))}
</ol>
) : <p>You can purchase items from the store.</p>
}
</div>
</div>
<div className="box">
<div className="content">
<h4>Store:</h4>
{state.store.length ?
(
<ol type="1">
{state.store.map((item) => (
<li key={item.id}>\
<button
onClick={() => buyItem(item)}
className="button">Buy
</button>
{item.name}
</li>
))}
</ol>
) : <p>No features</p>
}
</div>
<div className="content">
<h4>
Total Amount: ${state.car.price + state.additionalPrice}
</h4>
</div>
</div>
</div>
);
}
The actions that get dispatched contains the details of the selected item. We make use of the action type to determine how the reducer function will handle the updating of the state. You can see that the rendered view changes based on what you do - buying an item from the store removes the item from the store and adds it to the list of features. Also, the total amount gets updated. No doubt, there are some improvements that can be done to the application, this is only for learning purpose.
What about useState? Can’t we use that instead?
An astute reader may have been asking this all along. I mean, setState
is generally the same thing, right? Return a stateful value and a function to re-render a component with that new value.
const [state, setState] = useState(initialState);
We could have even used the useState()
hook in the counter example provided by the React docs. However, useReducer
is preferred in cases where state has to go through complicated transitions. Kent C. Dodds wrote up a explanation of the differences between the two and (while he often reaches for setState
) he provides a good use case for using userReducer
instead:
If your one element of your state relies on the value of another element of your state, then it's almost always best to use
useReducer
For example, imagine you have a tic-tac-toe game you're writing. You have one element of state called
squares
which is just an array of all the squares and their value[.]
My rule of thumb is to reach for useReducer
to handle complex states, particularly where the initial state is based on the state of other elements.
Oh wait, we already have Redux for this!
Those of you who have worked with Redux already know everything we’ve covered here and that’s because it was designed to use the Context API to pass stored states between components — without having to pass props through other components to get there.
So, does useReducer
replace Redux? Nope. I mean, you can basically make your own Redux by using it with the useContext
hook, but that’s doesn’t mean Redux is useless; Redux still has plenty of other features and benefits worth considering.
Where have you used userReducer
? Have you found clear-cut cases where it’s better than setState
? Maybe you can experiment with the things we covered here to build something. Here are a few ideas:
- A calendar that focus at today’s date but allows a user to select other dates. Maybe even add a “Today" button that returns the user to today’s date.
- You can try improving on the car example - have a list of cars that users can purchase. You might have to define this in the initial state, then the user can add extra features they want with a charge. These features can be predefined, or defined by the user.
The post Getting to Know the useReducer React Hook appeared first on CSS-Tricks.
from CSS-Tricks https://ift.tt/2X0lLkU
via IFTTT
Tuesday, 25 June 2019
Why I don’t use web components
Here’s an interesting post by Rich Harris where he’s made a list of some of the problems he’s experienced in the past with web components and why he doesn’t use them today:
Given finite resources, time spent on one task means time not spent on another task. Considerable energy has been expended on web components despite a largely indifferent developer population. What could the web have achieved if that energy had been spent elsewhere?
The most convincing part of Rich’s argument for me is where he writes about progressive enhancement and the dependence on polyfills for using web components today. And I’m sure that a lot of folks disagree with many of Rich’s points here, and there’s an awful amount of snark in the comments beneath his post, but it’s certainly an interesting conversation worth digging into. For an opposing perspective, go read the very last paragraph in the last installment of our Web Components Guide, where author Caleb Williams suggests that there's no need to wait to use web components in projects:
These standards are ready to adopt into our projects today with the appropriate polyfills for legacy browsers and Edge. And while they may not replace your framework of choice, they can be used alongside them to augment you and your organization’s workflows.
But all of this is a good reminder that hey: web components are a thing that we should be able to freely criticize and talk about without being jerks. And I think Rich does that pretty well.
Direct Link to Article — Permalink
The post Why I don’t use web components appeared first on CSS-Tricks.
from CSS-Tricks http://bit.ly/2IRkAPC
via IFTTT
Monday, 24 June 2019
Friday, 21 June 2019
Thursday, 20 June 2019
Hello Subgrid!
Rachel Andrew’s talk at CSSconf is wonderful because it digs into one of the most exciting changes that’s coming soon to a browser near you: subgrid! That’s a change to the CSS Grid spec that allows for much greater flexibility for our visual designs. Subgrid allows us to set one grid on an entire page and let child elements use that very same grid tracks.
The reason why I’m very excited is because this solves one of the most annoying visual layout issues that I’ve come across since becoming a web developer, and if that sounds bonkers and/or wonderful to you, then make sure to check out Rachel’s talk because she does a much better job of describing this than I possibly could:
Direct Link to Article — Permalink
The post Hello Subgrid! appeared first on CSS-Tricks.
from CSS-Tricks https://www.youtube.com/watch?v=vxOj7CaWiPU
via IFTTT
Wednesday, 19 June 2019
Drop caps & design systems
Ethan Marcotte has written up his process for how to make drop caps accessible for screen readers and browsers alike. All of that is very interesting and I’m sure I’ll use a technique like this in the near future, but the part that made me hop out of my seat is where Ethan notes his experience with design systems at Vox:
Since rolling out our new and improved drop caps, we’ve continued to iterate on them. (Including fixing a number of bugs that I, a professional web designer, introduced.) We’ve also discussed potential changes to the custom styles feature, in order to make it sustainable. But for my money, the real benefit of the work wasn’t the drop caps themselves, but the process that emerged from it.
This is something I’ve been thinking about a lot. The tricky thing to understanding design systems is that the process of creating and maintaining them is just as important than the code it uses. Sure, yes, fixing small things is very important, but the long-lasting improvements to a design system will always be around process. Why is this thing breaking? How long has it been broken for? How do we setup a way to make sure that this problem never pops up again?
Questions about process will always be the most useful questions to ask. The system will reward you for asking.
Direct Link to Article — Permalink
The post Drop caps & design systems appeared first on CSS-Tricks.
from CSS-Tricks http://bit.ly/31AzNwY
via IFTTT
Tuesday, 18 June 2019
Every Layout
Every Layout is a new work-in-progress website and book by Heydon Pickering and Andy Bell that explains how to make common layout patterns with CSS. They describe a lot of the issues when it comes to the design of these layouts, such as responsive problems and making sure we all write maintainable code, and then they’ve provided a handy generator at the end of each article to create our own little frameworks for dealing with these things.
They also have a complementary blog and one of the posts called "Algorithmic Design" caught my eye:
We make many of our biggest mistakes as visual designers for the web by insisting on hard coding designs. We break browsers’ layout algorithms by applying fixed positions and dimensions to our content.
Instead, we should be deferential to the underlying algorithms that power CSS, and we should think in terms of algorithms as we extrapolate layouts based on these foundations. We need to be leveraging selector logic, harnessing flow and wrapping behavior, and using calculations to adapt layout to context.
The tools for flexible, robust, and efficient web layout are there. We are just too busy churning out CSS to use them.
I’m looking forward to seeing where this project goes and how many more layouts these two end up documenting.
Direct Link to Article — Permalink
The post Every Layout appeared first on CSS-Tricks.
from CSS-Tricks http://bit.ly/2X7HVG3
via IFTTT
Monday, 17 June 2019
Friday, 14 June 2019
Components, yo.
I see VuePress just went 1.0. Explained simply, it's a static site generator based on Vue. But of course, you work in Vue, which means you work in components.
All the modern JavaScript frameworks are component-based. Even when they disagree with each other about specific things (like how Svelte requires compilation), they all seem to agree on the model of working in components. React is all components. A popular static site generator for React is Next.js. The Vue version of that is Nuxt.js.
Then there is Gatsby which is all React. (Listen to our latest ShopTalk Show as we discuss it.) Gridsome seems like the most 1-to-1 comparison in Vue-land, the notable comparison being how they both are designed to suck in data from any source. Components though, of course. I'm not sure there is a flagship Angular-based static site generator, but they are out there, and Angular is components all the way down.
Components are so ubiquitous that perhaps you don't even think about it anymore. But you might feel it, particularly if you jump back and forth between projects that aren't component-driven. WordPress development, generally, I feel, isn't component driven. Sure, you've got your header.php
and footer.php
files and such. You can break those apart however you want, but it's rather ad-hoc. You aren't explicitly building components and feeding those components local data and testing them as such. (You can get a lot closer with something like Timber.)
Building front-ends out of server-side code is absolutely fine. Server-side rendering is rife with advantages. But server-side languages don't seem to have embraced components the way JavaScript has. And since everyone seems to like components (front-end devs obviously love it, designers think that way anyway, back-end devs understand it...) it's no surprise to me to see this surge of beloved projects build server-side (or build-time) generated sites from JavaScript, simply because it's component-based and components are just a good idea.
The post Components, yo. appeared first on CSS-Tricks.
from CSS-Tricks http://bit.ly/2F9siUe
via IFTTT
Thursday, 13 June 2019
A11Y with Lindsey
Lindsey Kopacz has a wonderful blog about accessibility. I've seen a number of her articles making the rounds lately and I was like, dang I better make sure I'm subscribed. For example:
- An Introduction to ARIA States
- 3 Simple Tips to Improve Keyboard Accessibility
- Create custom keyboard accessible checkboxes
Regarding that last one, I remember learning from Sara Soueidan that a good tip for this to position them over the new custom checkboxes and hide them via opacity instead of hiding the native checkboxes by clipping them away. That covers the scenario of people exploring a touch screen for native interactive elements.
The post A11Y with Lindsey appeared first on CSS-Tricks.
from CSS-Tricks http://bit.ly/2KhwwNE
via IFTTT
Wednesday, 12 June 2019
Grid, content re-ordering and accessibility
Take this:
<ol>
<li>Get hungry</li>
<li>Order pizza</li>
<li>Eat pizza</li>
</ol>
That HTML ends up in the DOM that way (and thus how it is is exposed to assistive technology), and by default, those list items are also visually shown in that order. In most layout situations, the visual order will match that DOM order. Do nothing, and the list items will flow in the block direction of the document. Apply flexbox, and it will flow in the inline direction of the document.
But flexbox and grid also allow you to muck it up. Now take this:
ol {
display: flex;
flex-direction: row-reverse;
}
In this case, the DOM order still makes sense, but the visual order is all wrong. It's not just row-reverse
. There are a number of flexbox and grid properties that can get involved and confuse things: the order
property, flowing items into columns instead of rows, and positioning items specifically in unusual orders, among others. Even absolute positioning could cause the same trouble.
Manuel Matuzovic says:
If the visual order and the DOM order don’t match, it can irritate and confuse users up to a point where the experience is so bad that the site is unusable.
Rachel Andrew highlights this issue (including things we've published) as a big issue, and hopes we can get tools at the CSS level to help.
I think this is something we sorely need to address at a CSS level. We need to provide a way to allow the tab and reading order to follow the visual order. Source order is a good default, if you are taking advantage of normal flow, a lot of the time following the source is exactly what you want. However not always, not at every breakpoint. If we don’t give people a solution for this, we will end up with a mess. We’ve given people these great tools, and now I feel as if I’m having to tell people not to use them.
Direct Link to Article — Permalink
The post Grid, content re-ordering and accessibility appeared first on CSS-Tricks.
from CSS-Tricks http://bit.ly/2F8rLll
via IFTTT
Tuesday, 11 June 2019
Monday, 10 June 2019
Level up your .sort game
Sorting is a super handy JavaScript method that can display the values of an array in a certain order. Whether that’s real estate listings by price, burger joints by distance, or best nearby happy hours by rating, sorting arrays of information is a common need.
If you’re already doing this with JavaScript on a project, you are will likely using the built-in array .sort
method, which is in the same family of array methods that includes .filter
, .map
and .reduce
.
Let's take a look at how to do that!
A quick note about side effects
Before going into the details of how to use .sort
, there is a very important detail that needs to be addressed. While many of the ES5 array methods such as .filter
, .map
, and .reduce
will return a new array and leave the original untouched, .sort
will sort the array in place. If this is unwanted, an ES6 technique to avoid this is using the spread operator to concisely create a new array.
const foo = ['c','b','a'];
const bar = ['x','z','y'];
const fooSorted = foo.sort();
const barSorted = [...bar].sort();
console.log({foo, fooSorted, bar, barSorted});
/*
{
"foo": [ "a", "b", "c" ],
"fooSorted": [ "a", "b", "c" ],
"bar": [ "x", "z", "y" ],
"barSorted": [ "x", "y", "z" ]
}
*/
foo
and fooSorted
both reference the same array, but bar
and barSorted
are now individual arrays.
General overview
The only parameter of the .sort
method is a function. The spec refers to this as the compareFn
— I will refer to it as the "comparison function" for the rest of the post. This comparison function accepts two parameters, which I will refer to as a
and b
. a
and b
are the two elements that we will be comparing. If you do not provide a comparison function, the array will coerce each element into a string and sort according to Unicode points.
If you would like the a
to be ordered first in the array, the comparison function should return a negative integer; for b
, a positive integer. If you would like the two to maintain their current order, return a 0
.
If you don't understand, don't worry! Hopefully it will become much more clear with a few examples.
Comparing numbers
One of the simplest callbacks to write is a number comparison.
const numbers = [13,8,2,21,5,1,3,1];
const byValue = (a,b) => a - b;
const sorted = [...numbers].sort(byValue);
console.log(sorted); // [1,1,2,3,5,8,13,21]
If a
is greater than b
, a - b
will return a positive number, so b
will be sorted first.
Comparing strings
When comparing strings, the >
and <
operators will compare values based on each string’s Unicode value. This means that all uppercase letters will be “less” than all lowercase letters, which can lead to unexpected behavior.
JavaScript does have a method to help with comparing strings: the String.prototype.localeCompare
method. This method accepts a comparison string, a locale, and an options object. The options object accepts a few properties (all of which you can view here), but I find that the most useful is "sensitivity." This will affect how comparisons work between letter variations such as case and accent.
const strings = ['Über', 'alpha', 'Zeal', 'über', 'uber', 'Uber', 'Alpha', 'zeal'];
const sortBySensitivity = sensitivity => (a, b) => a.localeCompare(
b,
undefined, // locale string -- undefined means to use browser default
{ sensitivity }
);
const byAccent = sortBySensitivity('accent');
const byBase = sortBySensitivity('base');
const byCase = sortBySensitivity('case');
const byVariant = sortBySensitivity('variant'); // default
const accentSorted = [...strings].sort(byAccent);
const baseSorted = [...strings].sort(byBase);
const caseSorted = [...strings].sort(byCase);
const variantSorted = [...strings].sort(byVariant);
console.log({accentSorted, baseSorted, caseSorted, variantSorted});
/*
{
"accentSorted": [ "alpha", "Alpha", "uber", "Uber", "Über", "über", "Zeal", "zeal" ],
"baseSorted": [ "alpha", "Alpha", "Über", "über", "uber", "Uber", "Zeal", "zeal" ],
"caseSorted": [ "alpha", "Alpha", "über", "uber", "Über", "Uber", "zeal", "Zeal" ],
"variantSorted": [ "alpha", "Alpha", "uber", "Uber", "über", "Über", "zeal", "Zeal" ]
}
*/
To me, baseSorted
seems to be the most logical for most alphabetical sorting — ‘ü’, ‘u’, ‘Ü’, and ‘U’ are equivalent, so they remain in the order of the original array.
Running functions before comparing values
You may want to run a comparison function on a value that is derived from each array’s element. First, let’s write a comparison function factory that will "map" over the element before calling the comparison function.
const sortByMapped = (map,compareFn) => (a,b) => compareFn(map(a),map(b));
One use case for this is sorting based on the attribute of an object.
const purchases = [
{ name: 'Popcorn', price: 5.75 },
{ name: 'Movie Ticket', price: 12 },
{ name: 'Soda', price: 3.75 },
{ name: 'Candy', price: 5 },
];
const sortByMapped = (map,compareFn) => (a,b) => compareFn(map(a),map(b));
const byValue = (a,b) => a - b;
const toPrice = e => e.price;
const byPrice = sortByMapped(toPrice,byValue);
console.log([...purchases].sort(byPrice));
/*
[
{ name: "Soda", price: 3.75 },
{ name: "Candy", price: 5 },
{ name: "Popcorn", price: 5.75 },
{ name: "Movie Ticket", price: 12 }
]
*/
Another case might be to compare an array of dates.
const dates = ['2018-12-10', '1991-02-10', '2015-10-07', '1990-01-11'];
const sortByMapped = (map,compareFn) => (a,b) => compareFn(map(a),map(b));
const toDate = e => new Date(e).getTime();
const byValue = (a,b) => a - b;
const byDate = sortByMapped(toDate,byValue);
console.log([...dates].sort(byDate));
// ["1990-01-11", "1991-02-10", "2015-10-07", "2018-12-10"]
Reversing a sort
There are some cases where you may want to reverse the outcome of a comparison function. This is subtly different than doing a sort and then reversing the result in the way ties are handled: if you reverse the outcome, ties will also be reversed in order.
To write a higher order function that accepts a comparison function and returns a new one, you will need to flip the sign of the comparison’s return value.
const flipComparison = fn => (a,b) => -fn(a,b);
const byAlpha = (a,b) => a.localeCompare(b, null, { sensitivity: 'base' });
const byReverseAlpha = flipComparison(byAlpha);
console.log(['A', 'B', 'C'].sort(byReverseAlpha)); // ['C','B','A']
Running a tiebreaker sort
There are times when you may want to have a "tie-breaker" sort — that is, another comparison function that is used in the case of a tie.
By using [].reduce
, you can flatten an array of comparison functions into a single one.
const sortByMapped = map => compareFn => (a,b) => compareFn(map(a),map(b));
const flipComparison = fn => (a,b) => -fn(a,b);
const byValue = (a,b) => a - b;
const byPrice = sortByMapped(e => e.price)(byValue);
const byRating = sortByMapped(e => e.rating)(flipComparison(byValue));
const sortByFlattened = fns => (a,b) =>
fns.reduce((acc, fn) => acc || fn(a,b), 0);
const byPriceRating = sortByFlattened([byPrice,byRating]);
const restaurants = [
{ name: "Foo's Burger Stand", price: 1, rating: 3 },
{ name: "The Tapas Bar", price: 3, rating: 4 },
{ name: "Baz Pizza", price: 3, rating: 2 },
{ name: "Amazing Deal", price: 1, rating: 5 },
{ name: "Overpriced", price: 5, rating: 1 },
];
console.log(restaurants.sort(byPriceRating));
/*
{name: "Amazing Deal", price: 1, rating: 5}
{name: "Foo's Burger Stand", price: 1, rating: 3}
{name: "The Tapas Bar", price: 3, rating: 4}
{name: "Baz Pizza", price: 3, rating: 2}
{name: "Overpriced", price: 5, rating: 1}
*/
Writing a random sort
You might want to sort an array "randomly." One technique that I have seen is to use the following function as the comparison function.
const byRandom = () => Math.random() - .5;
Since Math.random()
returns a "random" number between 0
and 1
, the byRandom
function should return a positive number half of the time and a negative number the other half. This seems like it would be a good solution, but unfortunately, since the comparison function is not "consistent" — meaning it may not return the same value when called multiple times with the same values — it may result in some unexpected results.
For example, let's take an array of numbers between 0 and 4. If this byRandom
function was truly random, it would be expected that the new index of each number would be spread out equally over enough iterations. The original 0 value would be just as likely to be in index 4 as index 0 in the new array. However, in practice, this function will bias each number to its original position.
See the Pen
Array.sort() Random 👎 by Adam Giese (@AdamGiese)
on CodePen.
The "diagonal" from the top-left will statistically have the greatest value. In an ideal and truly random sort, each table cell would hover around 20%.
The fix for this is to find a way to ensure that the comparison function remains consistent. One way to do this is to map the random value to each array element before the comparison, then map it away after.
const sortByMapped = map => compareFn => (a,b) => compareFn(map(a),map(b));
const values = [0,1,2,3,4,5,6,7,8,9];
const withRandom = (e) => ({ random: Math.random(), original: e });
const toOriginal = ({original}) => original;
const toRandom = ({random}) => random;
const byValue = (a,b) => a - b;
const byRandom = sortByMapped(toRandom)(byValue);
const shuffleArray = array => array
.map(withRandom)
.sort(byRandom)
.map(toOriginal);
This ensures that each element has a single random value that is only calculated once per element rather than once per comparison. This removes the sorting bias towards the original position.
See the Pen
Array.sort() Random 👍 by Adam Giese (@AdamGiese)
on CodePen.
The post Level up your .sort game appeared first on CSS-Tricks.
from CSS-Tricks http://bit.ly/31k67nI
via IFTTT
Designing with Motifs
I love the way Erik Kennedy talks about digital design. Very practical and understandable. Have a listen to a chat with him we had on ShopTalk.
One of his latest blog posts is titled "The #1 Way to Spice Up Your Designs (And Create a More Cohesive Brand)" and it's about something he pegs as more of an intermediate (beyond the basics) level design tip about the idea of motifs.
In music, that might be a bit of a melody that asserts itself periodically and kinda informs the rest of the song. It's equally interesting in design, where a theme — perhaps a geometric element — is sprinkled in tastefully that helps the gestalt. Ties the room together, as they say.
Anyway, if you're serious about getting better at design, his course is where it's at and opens up in mid-June. So, now's the time to think about it.
Direct Link to Article — Permalink
The post Designing with Motifs appeared first on CSS-Tricks.
from CSS-Tricks http://bit.ly/2JMDQk6
via IFTTT
Friday, 7 June 2019
Thursday, 6 June 2019
What if we got aspect-ratio sized images by doing almost nothing?
Say you have an image you're using in an <img>
that is 800x600 pixels. Will it actually display as 800px wide on your site? It's very likely that it will not. We tend to put images into flexible container elements, and the image inside is set to width: 100%;
. So perhaps that image ends up as 721px wide, or 381px wide, or whatever. What doesn't change is that images aspect ratio, lest you squish it awkwardly (ignoring the special use-case object-fit
scenario).
So—we don't know how much vertical space an image is going to occupy until that image loads. This is the cause of jank! Terrible jank! It's everywhere and it's awful.
There are ways to create aspect-ratio sized boxes in HTML/CSS today. None of the options are particularly elegant, relying on the "hack" of setting a zero height and pushing the boxes height with padding. Wouldn't it be nicer to have a platform feature to help us here? The first crack at fixing this problem that I know about is an intrinsicsize
attribute. Eric Portis wrote about how this works wonderfully in Jank-Free Image Loads.
We'd get this:
<img src="image.jpg" intrinsicsize="800x600" />
This is currently behind a flag in Chrome 71+, and it really does help solve this problem.
But...
The intrinsicsize
property is brand new. It will only help on sites where the developers know about it and take the care to implement it. And it's tricky! Images tend to be of arbitrary size, and the intrinsicsize
attribute will need to be custom on every image to be accurate and do its job. That is, if it makes it out of standards at all.
There is another possibility! Eric also talked about the aspect-ratio
property in CSS as a potential solution. It's also still just a draft spec. You might say, but how is this helpful? It needs to be just as bespoke as intrinsicsize
does, meaning you'd have to do it as inline styles to be helpful. Maybe that's not so bad if it solves a big problem, but inline styles are such a pain to override and it seems like the HTML attribute approach is more inline with the spirit of images. Think of how srcset is a hint to browsers on what images are available to download and allowing it to pick the best. Telling the browser about the aspect-ratio
upfront is similarly useful.
I heard from Jen Simmons about an absolutely fantastic way to handle this: put a default aspect ratio into the UA stylesheet based on the elements existing width
and height
attributes. Like this:
img, iframe {
aspect-ratio: attr(width px) / attr(height px);
}
Let that soak in.
Now if you already have:
<img src="image.jpg" width="800" height="600" />
It automatically has the correct aspect ratio as the page loads. That's awesome.
- It's easy to understand.
- A ton of the internet already has these attributes sitting on their images already.
- New developers will have no trouble understanding this, and old developers will be grateful there is little if any work to do here.
I like the idea of the CSS feature. But I like 100 times more the idea of putting it into the UA stylesheet so that the entire web benefits. Changing a UA stylesheet, I'm sure, is no small thing to consider, and I'm not qualified to understand all the implications of that, but it feels like a very awesome thing at first consideration.
Jen has a ticket open for people to voice their thoughts and links to the bug ticket where Firefox is going to test this out to see how it goes.
The post What if we got aspect-ratio sized images by doing almost nothing? appeared first on CSS-Tricks.
from CSS-Tricks http://bit.ly/2K2gI1j
via IFTTT
Wednesday, 5 June 2019
JAMstack? More like SHAMstack.
I'm a fan of the whole JAMstack thing. It seems like a healthy web movement. I'm looking forward to both of the upcoming conferences.
Of any web trend, #jamstack seems like it will be the least regrettable.
— Chris Coyier (@chriscoyier) May 22, 2019
I feel like the acronym might not be quite doing it justice though. Not that I suggest we change it. Once a thing like that has legs, I find it's best to roll with it. Same deal with serverless. Heck, the name of this website is pretty... not great.
To me, the most important part of JAMstack is rooted in the concept of static file hosting. Static file hosting is the foundation of all the power. It opens up a bunch of doors, like:
- Everything can be CDN-hosted. "The edge," as they say. Even the HTML (the M in JAMStack also refers to Markup) can be CDN-hosted, which you otherwise can't do. That gives you an amazing base of speed that encourages you to keep that speed as you build.
- The project feels easier to work with. Git clone, npm install, build. Deployments are git pushes of a dist folder. It's so cool, for example, Netlify gives you a URL for every build, even on branches you're working on. This is made possible by deploys being kind of immutable. A set of files at a particular point in time.
- Cloud functions are awesome. Because you don't have a traditional server-side language to reach for, you build it with cloud functions when you do need server-side code — which is a cool way to architect things anyway and is very spiritually connected to all this.
Don't think, "Oh, JAMstack is just for Jekyll blogs," or whatever. True, static site generators are extremely JAMstack-y, and JAMstack highly encourages as much prebuilt markup as possible (which is good for speed and SEO and all that), but pre-built markup isn't a requirement.
I'd go so far as to say that a client-side JavaScript-powered app that ships a <div id="root"></div>
and a bundle of JavaScript that hits APIs and builds out the site is still a JAMstack site. It's still statically hosted (probably) with cloud functions serving up data.
I’d say “yes”.
Perhaps a little more SSR would be good for all the reasons but meh, not required for a jamstack merit badge.
— Chris Coyier (@chriscoyier) May 22, 2019
But as long as you're JAMStack anyway, that encourages you to put more in those static files. In that way, it encourages static content as well, when possible. I'd say "server-side rendered" (SSR) as that's the common term, but it's beyond that. It's not a server side language generating the markup on request; it's built in a build step ahead of time, before deployment. Again it's not required, just encouraged.
So, we've got static-hosted HTML, and all our other files (e.g. CSS, images, etc.) are also static. Then:
- The J of JAMstack is JavaScript.
- The A of JAMstack is APIs.
They are sorta kinda the same thing. Your JavaScript files are statically hosted. They run, and they talk to APIs if they need to. A common example might be a GraphQL endpoint coughing up some content.
An interesting twist here is that you can half-and-half this stuff. In other words, you can pre-build some of the markup, and wait for JavaScript and API calls for other parts. Imagine an e-commerce site with a homepage and a dozen other pages you can pre-build entirely, but then a catalog of thousands of products that would be too impractical to statically generate (too slow). They are just a single scaffolded template that flesh themselves out with client-side API calls.
So, if we were to make a new acronym, perhaps we'd include Static Hosting in there and combine the JavaScript and APIs into just APIs, leaving us with...
Static Hosting, APIs, and Markup, or the SHAMstack. Errrrr 😬 maybe not.
The post JAMstack? More like SHAMstack. appeared first on CSS-Tricks.
from CSS-Tricks http://bit.ly/2WpZtNN
via IFTTT
Self-Host Your Static Assets
Harry Roberts digs into why hosting assets on someone else’s servers (including CDNs) is not such a great idea if we want our websites to be lightning fast.
Harry writes:
One of the quickest wins—and one of the first things I recommend my clients do—to make websites faster can at first seem counter-intuitive: you should self-host all of your static assets, forgoing others’ CDNs/infrastructure.
I think perhaps the most shocking example Harry shows is this one:
...on a reasonably fast connection, hosting these static assets off-site is 311ms, or 1.65×, slower than hosting them ourselves.
By linking to three different origins in order to serve static assets, we cumulatively lose a needless 805ms to network negotiation. Full test. Okay, so not exactly terrifying, but Trainline, a client of mine, found that by reducing latency by 300ms, customers spent an extra £8m a year. This is a pretty quick way to make eight mill.
It’s clear from Harry’s example (as well as the rest of the examples on WPO stats) every millisecond counts when it comes to performance. And, if we can alleviate even a third of a second of latency by moving our assets around, we should probably go do that.
Direct Link to Article — Permalink
The post Self-Host Your Static Assets appeared first on CSS-Tricks.
from CSS-Tricks http://bit.ly/2WB76Aj
via IFTTT
Tuesday, 4 June 2019
Movin’ Modals Along a Path
Modals always be just appearin'. You might see one once in a while that slides in from one of the edges, or uses some kind of scale/opacity thing to appear from "above" or "below." But we can get weirder than that. Why not have them come in on an offset-path
?
Just a swoopy arc is kinda fun.
See the Pen
Move Modal In on Path by Chris Coyier (@chriscoyier)
on CodePen.
Or we could Mary Poppins it and have it come floating in from afar.
See the Pen
Move Modal In on Path: Mary Poppins Edition by Chris Coyier (@chriscoyier)
on CodePen.
Or get straight up wiggly woggly.
See the Pen
Move Modal In on Path: Wackadoo by Chris Coyier (@chriscoyier)
on CodePen.
That's all. I figured you were here for the CSS tricks, anyway. ;)
The post Movin’ Modals Along a Path appeared first on CSS-Tricks.
from CSS-Tricks http://bit.ly/2KsRg4y
via IFTTT
Monday, 3 June 2019
Do you need an ICON ONLY button without screwing up the accessibility?
The first consideration is: do you really? If you can, having text next to your icons is proven over and over again to be the most accessible and clearest UX (see Apple's latest blunder). But if you need to (and I get it, sometimes you need to), Sara Soueidan and Scott O'Hara have a pair of articles that nicely lay out all the options and present actual research on this topic.
- Sara Soueidan: Accessible Icon Buttons
- Scott O'Hara: Contextually Marking up accessible images and SVGs
If you just want to be told what to do, I'd go for the just use some text in the button approach:
<button aria-expanded="false" id="menu-trigger">
<svg viewBox="0 0 32 32" width="32px" height="32px"
aria-hidden="true" focusable="false">
<!-- svg content -->
</svg>
Menu
</button>
Sara says There is no One Way to Rule Them All, but it does seem like you really need to use actual text inside that button and either hide it or override it somehow. SVG alone has no rock solid way to provide an accessible name to a button or link.
Funny how long this has been a tricky pattern to get right.
The post Do you need an ICON ONLY button without screwing up the accessibility? appeared first on CSS-Tricks.
from CSS-Tricks http://bit.ly/314QWyD
via IFTTT
Prevent Page Scrolling When a Modal is Open
Please stop me if you've heard this one before. You open a modal, scroll through it, close it, and wind up somewhere else on the page than you were when you opened the modal.
That's because modals are elements on a page just like any other. It may stay in place (assuming that's what it's meant to do) but the rest of page continues to behave as normal.
See the Pen
Avoid body scrollable in safari when modal dialog shown by Geoff Graham (@geoffgraham)
on CodePen.
Sometimes this is a non-issue, like screens that are the exact height of the viewport. Anything else, though, we're looking at Scroll City. The good news is that we can prevent that with a sprinkle of CSS (and JavaScript) trickery.
Let's start with something simple
We can make a huge dent to open-modal-page-scrolling™ by setting the height of the entire body to the full height of the viewport and hiding vertical overflow when the modal is open:
body.modal-open {
height: 100vh;
overflow-y: hidden;
}
That's good and all, but if we've scrolled through the <body>
element before opening the modal, we get a little horizontal reflow. The width of the viewport is expanded about 15 pixels more, which is exactly the with of the scroll bar.
See the Pen
Avoid body scrollable in safari when modal dialog shown by Geoff Graham (@geoffgraham)
on CodePen.
Let's adjust the right padding of the body a bit to avoid that.
body {
height: 100vh;
overflow-y: hidden;
padding-right: 15px; /* Avoid width reflow */
}
Note that the modal needs to be shorter than the height of the viewport to make this work. Otherwise, the scroll bar on the body will be necessary.
Great, now what about mobile?
This solution works pretty great on desktop as well as Android Mobile. That said, Safari for iOS needs a little more love because the body still scrolls when a modal is open when tapping and moving about the touchscreen.
We can set the body to a fixed position as a workaround:
body {
position: fixed;
}
Works now! The body will not respond when the screen is touched. However, there's still a "small" problem here. Let's say the modal trigger is lower down the page and we click to open it up. Great! But now we're automatically scrolled back up to the top of the screen, which is just as disorientating as the scrolling behavior we're trying to resolve.
See the Pen
Avoid body scrollable in safari when modal dialog shown by Geoff Graham (@geoffgraham)
on CodePen.
Boo!
That's why we've gotta turn to JavaScript
We can use JavaScript to avoid the touch event bubble. We all know there should be a backdrop layer when a modal is open. Unfortunately, stopPropagation
is a little awkward with touch in iOS. But preventDefault
works well. That means we have to add event listeners in every DOM node contained in the modal — not just on the backdrop or the modal box layer. The good news is, many JavaScript libraries can do this, including good ol' jQuery.
Oh, and one more thing: What if we need scrolling inside the modal? We still have to trigger a response for a touch event, but when reaching the top or bottom of the modal, we still need to prevent bubbling. Seems very complex, so we're not totally out of the woods here.
Let's enhance the fixed body approach
This is what we were working with:
body {
position: fixed;
}
If we know the top of the scroll location and add it to our CSS, then the body will not scroll back to the top of the screen, so problem solved. We can use JavaScript for this by calculating the scroll top, and add that value to the body styles:
// When the modal is shown, we want a fixed body
document.body.style.position = 'fixed';
document.body.style.top = `-${window.scrollY}px`;
// When the modal is hidden, we want to remain at the top of the scroll position
document.body.style.position = '';
document.body.style.top = '';
This works, but there's still a little leakage here after the modal is closed. Specifically, it appears that the page already loses its scroll position when the modal is open and the body set to be fixed. So we have to retrieve the location. Let's modify our JavaScript to account for that.
// When the modal is hidden...
const top = document.body.style.top;
document.body.style.position = '';
document.body.style.top = '';
window.scrollTo(0, parseInt(scrollY || '0') * -1);
That does it! The body no longer scrolls when a modal is open and the scroll location is maintained both when the modal is open and when it is closed. Huzzah!
See the Pen
Avoid body scrollable in safari when modal dialog shown by Geoff Graham (@geoffgraham)
on CodePen.
The post Prevent Page Scrolling When a Modal is Open appeared first on CSS-Tricks.
from CSS-Tricks http://bit.ly/2JRpajX
via IFTTT
Passkeys: What the Heck and Why?
These things called passkeys sure are making the rounds these days. They were a main attraction at W3C TPAC 2022 , gained support in Saf...
-
Posted by Dr-Pete On December 3rd, Google announced that they were rolling out the latest Core Update . Initially, the bulk of the impact s...
-
Posted by MiriamEllis Image credit: Abraham Williams If you’re marketing big brands with hundreds or thousands of locations, are you cert...