Ads
Monday, September 30, 2024
Mostly Clear today!
With a high of F and a low of 37F. Currently, it's 55F and Fair outside.
Current wind speeds: 11 from the Northeast
Pollen: 0
Sunrise: September 30, 2024 at 06:47PM
Sunset: October 1, 2024 at 06:34AM
UV index: 0
Humidity: 32%
via https://ift.tt/YFneTMk
October 1, 2024 at 10:02AM
CSS Masonry & CSS Grid
An approach for creating masonry layouts in vanilla CSS is one of those “holy grail” aspirations. I actually tend to plop masonry and the classic “Holy Grail” layout in the same general era of web design. They’re different types of layouts, of course, but the Holy Grail was a done deal when we got CSS Grid.
That leaves masonry as perhaps the last standing layout from the CSS 3 era that is left without a baked-in solution. I might argue that masonry is no longer en vogue so to speak, but there clearly are use cases for packing items with varying sizes into columns based on available space. And masonry is still very much in the wild.
Steam is picking up on a formal solution. We even have a CSSWG draft specification for it. But notice how the draft breaks things out.
Grid-integrated syntax? Grid-independent syntax? We’ve done gone and multiplied CSS!
That’s the context for this batch of notes. There are two competing proposals for CSS masonry at the time of writing and many opinions are flying around advocating one or the other. I have personal thoughts on it, but that’s not important. I’ll be happy with whatever the consensus happens to be. Both proposals have merits and come with potential challenges — it’s a matter of what you prioritize which, in this case, I believe is a choice between leveraging existing CSS layout features and the ergonomics of a fresh new approach.
But let’s get to some notes from discussions that are already happening to help get a clearer picture of things!
What is masonry layout?
Think of it like erecting a wall of stones or bricks.
The sizes of the bricks and stones don’t matter — the column (or less commonly a row) is the boss of sizing things. Pack as many stones or bricks in the nearest column and then those adapt to the column’s width. Or more concisely, we’re laying out unevenly sized items in a column such that there aren’t uneven gaps between them.
Examples, please?
Here’s perhaps the most widely seen example in a CodePen, courtesy of Dave DeSandro, using his Masonry.js tool:
I use this example because, if I remember correctly, Masonry.js was what stoked the masonry trend in, like 2010 or something. Dave implemented it on Beyoncé’s website which certainly gave masonry a highly visible profile. Sometimes you might hear masonry called a “Pinterest-style” layout because, well, that’s been the site’s signature design — perhaps even its brand — since day one.
Here’s a faux example Jhey put together using flexbox:
Chris also rounded up a bunch of other workarounds in 2019 that get us somewhat there, under ideal conditions. But none of these are based on standardized approaches or features. I mean, columns and flexbox are specced but weren’t designed with masonry in mind. But with masonry having a long track record of being used, it most certainly deserves a place in the CSS specs.
There are two competing proposals
This isn’t exactly news. In fact, we can get earlier whiffs of this looking back to 2020. Rachel Andrew introduced the concept of making masonry a sub-feature of grid in a Smashing Magazine article.
Let’s fast-forward to 2022. We had an editor’s draft for CSS Masonry baked into the CSS Grid Layout Module 3 specification. Jenn Simmons motioned for the CSSWG to move it forward to be a first public working draft. Five days later, Chromium engineer Ian Kilpatrick raised two concerns about moving things forward as part of the CSS Grid Layout module, the first being related to sizing column tracks and grid’s layout algorithm:
Grid works by placing everything in the grid ahead of time, then sizing the rows/columns to fit the items. Masonry fundamentally doesn’t work this way as you need to size the rows/columns ahead of time – then place items within those rows/columns.
As a result the way the current specification re-uses the grid sizing logic leads to poor results when intrinsically sizing tracks, and if the grid is intrinsically-sized itself (e.g. if its within a grid/flex/table, etc).
Good point! Grid places grid items in advance ahead of sizing them to fit into the available space. Again, it’s the column’s size that bosses things around in masonry. It logically follows that we would need to declare masonry and configure the column track sizes in advance to place things according to space. The other concern concerns accessibility as far as visual and reading order.
That stopped Jenn’s motion for first public working draft status dead in its tracks in early 2023. If we fast-forward to July of this year, we get Ian’s points for an alternative path forward for masonry. That garnered support from all sorts of CSS heavyweights, including Rachel Andrew who authored the CSS Grid specification.
And, just a mere three weeks ago from today, fantasai shared a draft for an alternate proposal put together with Tab Atkins. This proposal, you’ll see, is specific to masonry as its own module.
And thus we have two competing proposals to solve masonry in CSS.
The case for merging masonry and grid
Rounding up comments from GitHub tickets and blog posts…
Flexbox is really designed for putting things into a line and distributing spare space. So that initial behaviour of putting all your things in a row is a great starting point for whatever you might want to do. It may be all you need to do. It’s not difficult as a teacher to then unpack how to add space inside or outside items, align them, or make it a column rather than a row. Step by step, from the defaults.
I want to be able to take the same approach with
display: masonry
.[…]
We can’t do that as easily with grid, because of the pre-existing initial values. The good defaults for grid don’t work as well for masonry. Currently you’d need to:
Rachel Andrew, “Masonry and good defaults”
- Add
display: grid
, to get a single column grid layout.- Add
grid-template-columns: <track-listing>
, and at the moment there’s no way to auto-fillauto
sized tracks so you’ll need to decide on how many. Usinggrid-template-columns: repeat(3, auto)
, for example.- Add
grid-template-rows: masonry
.- Want to define rows instead? Switch the
masonry
value to apply togrid-template-columns
and now define your rows. Once again, you have to explicitly define rows.
For what it’s worth, Rachel has been waving this flag since at least 2020. The ergonomics of display: masonry
with default configurations that solve baseline functionality are clear and compelling. The default behavior oughta match the feature’s purpose and grid just ain’t a great set of default configurations to jump into a masonry layout. Rachel’s point is that teaching and learning grid to get to understand masonry behavior unnecessarily lumps two different formatting contexts into one, which is a certain path to confusion. I find it tough to refute this, as I also come at this from a teaching perspective. Seen this way, we might say that merging features is another lost entry point into front-end development.
In recent years, the two primary methods we’ve used to pull off masonry layouts are:
- Flexbox for consistent row sizes. We adjust the
flex-basis
based on the item’s expected percentage of the total row width.- Grid for consistent column sizes. We set the row span based on the expected aspect ratio of the content, either server-side for imagery or client-side for dynamic content.
What I’ve personally observed is:
Tyler Sticka, commenting on GitHub Issue #9041
- Neither feels more intuitive than the other as a starting point for masonry. So it feels a little itchy to single out Grid as a foundation.
- While there is friction when teaching folks when to use a Flexbox versus a Grid, it’s a much bigger leap for contributors to wrap their heads around properties that significantly change behavior (such as
flex-wrap
orgrid-auto-flow: dense
).
It’s true! If I had to single out either flexbox or grid as the starting poit for masonry (and I doubt I would either way), I might lean flexbox purely for the default behavior of aligning flexible items in a column.
The syntax and semantics of the CSS that will drive masonry layout is a concern that is separate from the actual layout mechanics itself, which internally in implementation by user agents can still re-use parts of the existing mechanics for grids, including subgrids. For cases where masonry is nested inside grid, or grid inside masonry, the relationship between the two can be made explicit.
@jgotten, commenting on GitHub Issue #9041
Rachel again, this time speaking on behalf of the Chrome team:
There are two related reasons why we feel that masonry is better defined outside of grid layout—the potential of layout performance issues, and the fact that both masonry and grid have features that make sense in one layout method but not the other.
The case for keeping masonry separate from grid
One of the key benefits of integrating masonry into the grid layout (as in CASE 2) is the ability to leverage existing grid features, such as subgrids. Subgrids allow for cohesive designs among child elements within a grid, something highly desirable in many masonry layouts as well. Additionally, I believe that future enhancements to the grid layout will also be beneficial for masonry, making their integration even more valuable. By treating masonry as an extension of the grid layout, developers would be able to start using it immediately, without needing to learn a completely new system.
Kokomi, commenting on GitHub Issue #9041
It really would be a shame if keeping masonry separate from grid prevents masonry from being as powerful as it could be with access to grid’s feature set:
I think the arguments for a separate
Angel Ponce, commenting on GitHub Issue #9041display: masonry
focus too much on the potential simplicity at the expense of functionality. Excluding Grid’s powerful features would hinder developers who want or need more than basic layouts. Plus, introducing another display type could lead to confusion and fragmentation in the layout ecosystem.
Rachel counters that, though.
I want express my strong support for adding masonry to display:grid. The fact that it gracefully degrades to a traditional grid is a huge benefit IMO. But also, masonry layout is already possible (with some constraints) in Grid layout today!
Naman Goel, Angel Ponce, commenting on GitHub Issue #9041
Chris mildly voiced interest in merging the two in 2020 before the debate got larger and more heated. Not exactly a ringing endorsement, but rather an acknowledgment that it could make sense:
I like the
grid-template-rows: masonry;
syntax because I think it clearly communicates: “You aren’t setting these rows. In fact, there aren’t even really rows at all anymore, we’ll take care of that.” Which I guess means there are no rows to inherit in subgrid, which also makes sense.
Where we at?
Collecting feedback. Rachel, Ian, and Tab published a joint call for folks like you and me to add our thoughts to the bag. That was eight days ago as of this writing. Not only is it a call to action, but it’s also an excellent overview of the two competing ideas and considerations for each one. You’ll want to add your feedback to GitHub Issue #9041.
CSS Masonry & CSS Grid originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/bFmycqK
via IFTTT
Sunday, September 29, 2024
Clear today!
With a high of F and a low of 54F. Currently, it's 65F and Clear outside.
Current wind speeds: 12 from the South
Pollen: 0
Sunrise: September 29, 2024 at 06:46PM
Sunset: September 30, 2024 at 06:36AM
UV index: 0
Humidity: 31%
via https://ift.tt/ub5WVA8
September 30, 2024 at 10:02AM
Saturday, September 28, 2024
Clear today!
With a high of F and a low of 53F. Currently, it's 63F and Clear outside.
Current wind speeds: 9 from the Southeast
Pollen: 0
Sunrise: September 28, 2024 at 06:45PM
Sunset: September 29, 2024 at 06:37AM
UV index: 0
Humidity: 31%
via https://ift.tt/1JYS4uz
September 29, 2024 at 10:02AM
Friday, September 27, 2024
Clear today!
With a high of F and a low of 50F. Currently, it's 64F and Clear outside.
Current wind speeds: 5 from the East
Pollen: 0
Sunrise: September 27, 2024 at 06:44PM
Sunset: September 28, 2024 at 06:39AM
UV index: 0
Humidity: 50%
via https://ift.tt/VJGjXwC
September 28, 2024 at 10:02AM
Slide Through Unlimited Dimensions With CSS Scroll Timelines
The creator of CSS has said he originally envisaged CSS as the main web technology to control behavior on web pages, with scripting as a fallback when things weren’t possible declaratively in CSS. The rationale for a CSS-first approach was that “scripting is programming and programming is hard.” Since introducing the :hover
pseudo-class, CSS has been standardizing patterns developers create in JavaScript and “harvesting” them into CSS standards. When you think about it like that, it’s almost as if JavaScript is the hack and CSS is the official way.
We can, therefore, feel less dirty implementing script-like behavior with CSS, and we shouldn’t be surprised that something like the new scroll-timeline
feature has appeared with pretty good browser support. Too many developers implemented clever parallax scrolling websites, which has summoned the CSS feature genie we cannot put back in its bottle. If you don’t want janky main-thread animations for your next parallax-scrolling website, you must now come to the dark side of hacking CSS. Just kidding, there is also a new JavaScript API for scroll-linked animations if imperative programming better fits your use case.
Migrating a JavaScript sample to CSS
It was satisfyingly simple to fork Chris Coyier’s pre-scroll-timeline
example of a scroll-linked animation by replacing the CSS Chris was using to control the animations with just one line of CSS and completely deleting the JavaScript!
body, .progress, .cube {
animation-timeline: scroll();
}
Using the scroll()
function without parameters sets up an “anonymous scroll progress timeline” meaning the browser will base the animation on the nearest ancestor that can scroll vertically if our writing mode is English. Unfortunately, it seems we can only choose to animate based on scrolling along the x or y-axis of a particular element but not both, which would be useful. Being a function, we can pass parameters to scroll()
, which provides more control over how we want scrolling to run our animation.
Experimenting with multiple dimensions
Even better is the scroll-scope
property. Applying that to a container element means we can animate properties on any chosen ancestor element based on any scrollable element that has the same assigned scope. That got me thinking… Since CSS Houdini lets us register animation-friendly, inheritable properties in CSS, we can combine animations on the same element based on multiple scrollable areas on the page. That opens the door for interesting instructional design possibilities such as my experiment below.
Scrolling the horizontal narrative on the light green card rotates the 3D NES console horizontally and scrolling the vertical narrative on the dark green card rotates the NES console vertically. In my previous article, I noted that my past CSS hacks have always boiled down to hiding and showing finite possibilities using CSS. What interests me about this scroll-based experiment is the combinatorial explosion of combined vertical and horizontal rotations. Animation timelines provide an interactivity in pure CSS that hasn’t been possible in the past.
The implementation details are less important than the timeline-scope
usage and the custom properties. We register two custom angle properties:
@property --my-y-angle {
syntax: "<angle>";
inherits: true;
initial-value: 0deg;
}
@property --my-x-angle {
syntax: "<angle>";
inherits: true;
initial-value: -35deg;
}
Then, we “borrow” the NES 3D model from the samples in Julian Garner’s amazing CSS 3D modeling app. We update the .scene
class for the 3D to base the rotation on our new variables like this:
.scene {
transform: rotateY(var(--my-y-angle)) rotateX(var(--my-x-angle));
}
Next, we give the <body>
element a timeline-scope
with two custom-named scopes.
body {
timeline-scope: --myScroller,--myScroller2;
}
I haven’t seen anything officially documented about passing in multiple scopes, but it does work in Google Chrome and Edge. If it’s not a formally supported feature, I hope it will become part of the standard because it is ridiculously handy.
Next, we define the named timelines for the two scrollable cards and the axes we want to trigger our animations.
.card:first-child {
scroll-timeline-axis: x;
scroll-timeline-name: --myScroller;
}
.card:nth-child(2) {
scroll-timeline-axis: y;
scroll-timeline-name: --myScroller2;
}
And add the animations to the scene:
.scene {
animation: rotateHorizontal,rotateVertical;
animation-timeline: --myScroller,--myScroller2;
}
@keyframes rotateHorizontal {
to {
--my-y-angle: 360deg;
}
}
@keyframes rotateVertical {
to {
--my-x-angle: 360deg;
}
}
Since the 3D model inherits the x and y angles from the document body, scrolling the cards now rotates the model in combinations of vertical and horizontal angle changes.
User-controlled animations beyond scrollbars
When you think about it, this behavior isn’t just useful for scroll-driven animations. In the above experiment, we are using the scrollable areas more like sliders that control the properties of our 3D model. After getting it working, I went for a walk and was daydreaming about how cool it would be if actual range inputs could control animation timelines. Then I found out they can! At least in Chrome. Pure CSS CMS anyone?
While we’re commandeering 3D models from Julian Garner, let’s see if we can use range inputs to control his X-wing model.
It’s mind-boggling that we can achieve this with just CSS, and we could do it with an arbitrary number of properties. It doesn’t go far enough for me. I would love to see other input controls that can manipulate animation timelines. Imagine text fields progressing animations as you fill them out, or buttons able to play or reverse animations. The latter can be somewhat achieved by combining the :active
pseudo-class with the animation-play-state
property. But in my experience when you try to use that to animate multiple custom properties, the browser can get confused. By contrast, animation timelines have been implemented with this use case in mind and therefore work smoothly and exactly as I expected.
I’m not the only one who has noticed the potential for hacking this emergent CSS feature. Someone has already implemented this clever Doom clone by combining scroll-timeline with checkbox hacks. The problem I have is it still doesn’t go far enough. We have enough in Chrome to implement avatar builders using scrollbars and range inputs as game controls. I am excited to experiment with unpredictable, sophisticated experiences that are unprecedented in the era before the scroll-timeline feature. After all, if you had to explain the definition of a video game to an alien, wouldn’t you say it is just a hyper-interactive animation?
Slide Through Unlimited Dimensions With CSS Scroll Timelines originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/NdcJqPI
via IFTTT
Aggregating my distributed self
Miriam Suzanne’s in the middle of a redesign of her personal website. It began in August 2022. She’s made an entire series out of the work that’s worth your time, but I wanted to call out the fifth and latest installment because she presents a problem that I think we can all relate to:
But the walls got in my way. Instead of minimal renovation, I got just far enough to live with it and then started a brand new Eleventy repo.
The plan was to prototype […] and bring back well-formed solutions. To echo Dave Rupert, prototyping is useful. It’s easier to play with new ideas when you’re not carrying a decade of content and old code along with you.
But prototyping evolved into what I would call tinkering (complimentary). Maybe I mean procrastinating (also complimentary), but it’s a wandering process that also helps me better understand what I want from a website. I might not make visible progress over two years, but I start to form a point of view […]. Keeping things easy is always where things get complicated. And it brings me back to where my redesign started – a desire to clarify the information architecture. Not only for visitors, but for myself.
Don’t even tell me you’ve never been there! Jim Neilsen blogged along similar lines. You get a stroke of inspiration that’s the kernel of some idea that motivates you to start, you know, working on it. There’s no real plan, perhaps. The idea and inspiration are more than enough to get you going… that is until you hit a snag. And what I appreciate about Miriam’s post is that she’s calling out content as the snag. Well, not so much a snag as a return to the founding principle for the redesign: a refined content architecture.
- Sometimes I do events where I speak, or teach a workshop, or perform. Events happen at a time and place.
- Sometimes I create artifacts like a book or an album, a website, or specification. Artifacts often have a home URL. They might have a launch date, but they are not date-specific.
- Some of my projects are other channels with their own feeds, their own events and artifacts.
- Those channels are often maintained by an organization that I work with long-term. A band, a web agency, a performance company, etc.
These boundaries aren’t always clean. A post that remains relevant could be considered an artifact. Events can generate artifacts, and vice versa. An entire organization might exist to curate a single channel.
So, Miriam’s done poking at visual prototypes and ready to pour the filling into the pie crust. I relate with this having recently futzed with the content architecure of this site. I find it tough to start with a solidified design before I know what content is going into it. But I also find it tough to work with no shape at all. In my case, CSS-Tricks has a well-established design that’s evolved, mostly outside of me. I love the design but it’s an inherited one and I’m integrating content around it. Design is the constraint. If I had the luxury of stripping the building to the studs, I might take a different approach because then I could “paint” around it. Content would be the constraint.
It’s yet another version of the Chicken-Egg dilemma. I still think of the (capital-W) Web as a content medium at least in a UA style sense in that it’s the default. It’s more than that, of course. I’m a content designer at heart (and trade) but I’m hesitant to cry “content is king” which reminded me of something I wrote for an end-of-year series we did here answering the question: What is one thing people can do to make their website better? My answer: Read your website.
We start to see the power of content when we open up our understanding of what it is, what it does, and where it’s used. That might make content one of the most extensible problem-solving tools in your metaphorical shed—it makes sites more accessible, extracts Google-juicing superpowers, converts sales, and creates pathways for users to accomplish what they need to do.
And as far as prioritizing content or design, or…?
The two work hand-in-hand. I’d even go so far as to say that a lot of design is about enhancing what is communicated on a page. There is no upstaging one or the other. Think of content and design as supporting one another, where the sum of both creates a compelling call-to-action, long-form post, hero banner, and so on. We often think of patterns in a design system as a collection of components that are stitched together to create something new. Pairing content and design works much the same way.
I’d forgotten those words, so I appreciate Miriam giving me a reason to revisit them. We all need to be recalibrated every so often — swap out air filters, top off the fluids, and rotate the ol’ tires. And an old dog like me needs it a little more often. I spent a few more minutes in that end-of-year series and found a few other choice quotes about the content-design continuum that may serve as inspiration for you, me, or maybe even Miriam as she continues the process of aggragating her distributed self.
This sounds serious, but don’t worry — the site’s purpose is key. If you’re building a personal portfolio, go wild! However, if someone’s trying to file a tax return, whimsical loading animations aren’t likely to be well-received. On the other hand, an animated progress bar could be a nice touch while providing visual feedback on the user’s action.
Cassie Evans, “Empathetic Animation”
Remember, the web is an interactive platform — take advantage of that, where appropriate (less is more, accessibility is integral, and you need to know your audience). Whether that’s scrollytelling, captioned video, and heck, maybe for your audience, now’s the time to start looking into AR/VR! Who knows. Sometimes you just need to try stuff out and see what sticks. Just be careful. Experimentation is great, but we need to make sure we’re bringing everyone along for the ride.
Mel Choyce, “Show, Don’t Tell”
Your personal site is a statement of who you are and what you want to do. If you showcase your favorite type of work, you’ll get more requests for similar projects or jobs — feeding back into a virtuous cycle of doing more of what you love.
Amelia Wattenberger, “Exactly What You Want”
And one of my favorites:
But the prime reason to have a personal website is in the name: it is your personalhome on the web. Since its early days, the web has been about sharing information and freedom of expression. Personal websites still deliver on that promise. Nowhere else do you have that much freedom to create and share your work and to tell your personal story. It is your chance to show what you stand for, to be different, and to be specific. Your site lets you be uniquely you and it can be whatever you imagine it to be.
So if you have a personal site, make sure to put in the work and attention to make it truly yours. Make it personal. Fine-tune the typography, add a theme switcher, or incorporate other quirky little details that add personality. As Sarah Drasner writes, you can feel it if a site is done with care and excitement. Those are the sites that are a joy to visit and will be remembered.
Matthias Ott, “Make it Personal”
That last one has the added perk of reminding me how incredibly great Sarah Drasner is.
Aggregating my distributed self originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/LhVZATu
via IFTTT
Thursday, September 26, 2024
Mostly Clear today!
With a high of F and a low of 58F. Currently, it's 68F and Clear outside.
Current wind speeds: 11 from the South
Pollen: 0
Sunrise: September 26, 2024 at 06:43PM
Sunset: September 27, 2024 at 06:40AM
UV index: 0
Humidity: 42%
via https://ift.tt/zbfXwvB
September 27, 2024 at 10:02AM
Catching Up on the WordPress 🚫 WP Engine Sitch
Many of you — perhaps most of you — have been sitting on the sidelines while WordPress and WP Engine trade legal attacks on one another. It’s been widely covered as we watch it unfold in the open; ironically, in a sense.
These things can take twists and turns and it doesn’t help that this just so happens to be an emotionally charged topic in certain circles. WordPress is still the leading CMS after all these years and by a long shot. Many developers make their living in the WordPress ecosystem. All of those developers need hosting. WP Engine is still the leading WordPress-flavored host after many years. Many developers host their agencies there and use it to administrate their clients’ sites.
And I haven’t even gotten to the drama. That’s not really the point. The point is that there’s a bunch of heated words flying around and it can be difficult to know where they’re coming from, who they are aimed at, and most importantly, why they’re being said in the first place. So, I’m going to round up a few key voices contributing to the discussion for the sake of context and to help catch up.
Editor’s Note: Even though CSS-Tricks has no involvement with either company, I think it’s mentioning that Automattic was a looooooong time sponsor. This site was also once hosted by Flywheel, a company acquired by WP Engine before we moved to Cloudways following the DigitalOcean acquisition. Me? My personal site runs on WP Engine, but I’m not precious about it having only been there one year.
Prelude to a tweet
We had fair warning that something was coming up when WordPress co-founder Matt Mullenweg sent this out over X:
I know private equity and investors can be brutal (read the book Barbarians at the Gate). Please let me know if any employee faces firing or retaliation for speaking up about their company's participation (or lack thereof) in WordPress. We'll make sure it's a big public deal and…
— Matt Mullenweg (@photomatt) September 19, 2024
There’s the ammo: Don’t let private equity bully you into speaking up against the company you work for when its contributions to WordPress are on the slim side of things.
Private equity. Lack of participation in the WordPress community. Making a big public deal of it. Remember these things because this is one day before…
WordCamp US 2024
Matt spoke at WordCamp US (WCUS) 2024 in Portland, OR, last week. September 20 to be exact. Making big, bold statements at WCUS isn’t a new thing for Matt, as many of us still have “Learn JavaScript deeply” tattooed on the brain from 2016.
Matt’s statements this year were less inspirational (instructional?) as they took direct aim at WP Engine as part of a presentation on the merits of open-source collaboration. You can watch and listen to where the first jab was thrown roughly around the 10:05 marker of the recording.
Let’s break down the deal. Matt begins by comparing the open-source contributions to WordPress from his company, Automattic, to those of WP Engine. These things are tracked on WordPress.org as part of a campaign called “Five for the Future” that’s designed to give organizations an influential seat at the table to form the future of WordPress in exchange for open-source contributions back to the WordPress project. Automattic has a page totaling its contributions. So does WP Engine.
Before Matt reveals the numbers, he goes out of his way to call out the fact that both Automattic and WP Engine are large players in the neighborhood of $500 million dollars. That’s the setup for Matt to demonstrate how relatively little WP Engine contributes to WordPress against Matt’s own company. Granted, I neither have absolutely no clue what factors into contributions, nor how the pages are administrated or updated. But here’s what they show…
Quite the discrepancy! I’d imagine Automattic dwarfs every other company that’s pledged to the campaign. Maybe it would be better to compare the contributions of another non-Automattic pledge that has a fairly strong reputation for participating in WordPress community. 10up is one of the companies that comes straight to my mind and they are showing up for 191 hours per week, or roughly five times WP Engine’s reported time. I get conflicting info on 10up’s revenue, valuation, and size, so maybe the comparison isn’t fair. Or maybe it is fair because 10up is certainly smaller than WP Engine, and no estimate I saw was even close to the $500 million mark.
Whatever the case, bottom line: Matt calls out WP Engine for its lack of effort on a very public stage — maybe the largest — in WordPress Land. He doesn’t stop there, going on to namecheck Silver Lake, a ginormous private equity firm bankrolling the company. The insinuation is clear: there’s plenty of money and resources, so pony up.
That’s bad enough for attendees to raise eyebrows, but it doesn’t end there. Matt encourages users and developers alike to vote with money by not purchasing hosting from WP Engine (11:31) and seems to suggest (23:05) that he’ll provide financial support to any WP Engine employees who lose their jobs from speaking up against their employer.
I think I can get behind the general idea that some companies need a little prodding to pull their weight to something like the Five for the Future campaign. Encouraging developers to pull their projects from a company and employees to jeopardize their careers? Eek.
“WP Engine is not WordPress”
This is when I believe things got noisy. It’s one thing to strongarm a company (or its investors) into doing more for the community. But in a post on his personal blog the day after WCUS, Matt ups the ante alleging that “WP Engine isn’t WordPress.” You’d think this is part of the tough-guy stance he had from the stage, but his argument is much different in this post. Notice it’s about how WP Engine uses WordPress in its business rather than how much the company invests in it:
WordPress is a content management system, and the content is sacred. Every change you make to every page, every post, is tracked in a revision system, just like the Wikipedia. This means if you make a mistake, you can always undo it. It also means if you’re trying to figure out why something is on a page, you can see precisely the history and edits that led to it. These revisions are stored in our database. This is very important, it’s at the core of the user promise of protecting your data, and it’s why WordPress is architected and designed to never lose anything.
WP Engine turns this off. They disable revisions because it costs them more money to store the history of the changes in the database, and they don’t want to spend that to protect your content. It strikes to the very heart of what WordPress does, and they shatter it, the integrity of your content.
OK, gloves off. This is more personal. It’s no longer about community contributions but community trust and how WP Engine erodes trust by preventing WordPress users from accessing core WordPress features for their own profit.
Required reading
That’s where I’d like to end this, at least for now. Several days have elapsed since Matt’s blog post and there are many, many more words flying around from him, community members, other companies, and maybe even your Great Aunt. But if you’re looking for more signal than noise, I’ve rounded up a few choice selections that I feel contribute to the (heated) discussion.
Reddit: Matt Mullenweg needs to step down from WordPress.org leadership ASAP
Matt responds to the requisite calls for him to step down, starting with:
To be very clear, I was 100% cordial and polite to everyone at the booth, my message was:
* I know this isn’t about them, it’s happening several levels above, it’s even above their CEO, it’s coming from their owner, Silver Lake and particularly their board member Lee Wittlinger.
* Several people inside WP Engine have been anonymously leaking information to me about their bad behavior, and I wanted to let them know if they were caught or faced retaliation that I would support them in every way possible, including covering their salaries until they found a new job.
* That *if* we had to take down the WP Engine booth and ban WP Engine that evening, my colleague Chloé could print them all new personal badges if they still wanted to attend the conference personally, as they are community members, not just their company.
This was delivered calmly, and they said thank you, and their head of comms, Lauren Cox, who was there asked that they have time to regroup and discuss.
Automattic’s Actionable Misconduct Directed to WP Engine
WP Engine issues a cease and desist letter designed to stop Matt from disparaging them publicly. But hold up, because there’s another juicy claim in there:
In the days leading up to Mr. Mullenweg’s September 20th keynote address at the WordCamp US Convention, Automattic suddenly began demanding that WP Engine pay Automattic large sums of money, and if it didn’t, Automattic would wage a war against WP Engine.
And yes, they did issue it from their own site’s
/wp-content
directory. That’s easy to lose, so I’ve downloaded it to link it for posterity.
Open Source, Trademarks, and WP Engine
Just today, Matt published a cease and desist letter to the Auttomatic blog where he alleges that WP Engine’s commercial modifications to WordPress Core violate the WordPress trademark. Again, this has become about licensing, not contributions:
WP Engine’s business model is based on extensive and unauthorized use of these trademarks in ways that mislead consumers into believing that WP Engine is synonymous with WordPress. It’s not.
This is trademark abuse, not fair competition.
This is no longer WordPress vs. WP Engine. It’s more like Automattic vs. WP Engine. But with Matt’s name quite literally in the name Automattic, let’s be real and call this Matt Mullenweg vs. WP Engine.
WP Tavern coverage
WP Tavern is still the closest thing we have to an official WordPress news outlet. Nevermind that it’s funded and hired by Automattic (among others). I respect it, though I honestly have been less attentive to it since the team turned earlier this year. It’s still a great spot to catch up on the post-event coverage:
- Highlights from Matt Mullenweg’s Spiciest Word Camp Presentation at WordCamp US 2024 (Sep. 24)
- Automattic Responds to WP Engine’s Cease and Desist with Legal Action (Sep. 24)
There’s another more recent WP Tavern article I want to call out because it’s a huge development in this saga…
WP Engine Banned from Using WordPress.org Resources
Dang. This is the point of no return. It not only affects WP Engine proper, but the Flywheel hosting it also owns.
WordPress.org has blocked WP Engine customers from updating and installing plugins and themes via WP Admin.
I was able to update plugins on my site as recently as yesterday, but let’s see as of this morning.
Maybe I can still see details about my installed plugins…
This is a bad, bad situatiuon. I have thoughts about it and neither side looks good. Using real people with no dog in the fight to make a point is never gonna be a good look. Then again, both sides have valid points and I can see where they’re coming from. I just hate to see it come to a head like this.
Catching Up on the WordPress 🚫 WP Engine Sitch originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/F0E59Lb
via IFTTT
BCD Watch
A new tool from Eric Meyer, Brian Kardell, and Stephanie Stimac backed with Igalia’s support. Brian announced it on his blog, as did Eric, describing it like this:
What BCD Watch does is, it grabs releases of the Browser Compatibility Data (BCD) repository that underpins the support tables on MDN and services like caniuse.com. It then analyzes what’s changed since the previous release.
Every Monday, BCD Watch produces two reports. The Weekly Changes Report lists all the changes to BCD that happened in the previous week — what’s been added, removed, or renamed in the whole of BCD. It also tells you which of the Big Three browsers newly support (or dropped support for) each listed feature, along with a progress bar showing how close the feature is to attaining Baseline status.
Browser support data is at MDN. There’s also plenty at Caniuse.com. The two share data, in fact, though not all of it. We now have Baseline, which is also cited in MDN and Caniuse alike. It’s nice to see an effort at cracking a central spot for all this — organized by date, no less.
Oh, and hey, there’s a feed. Even better.
You can also poke at its repo. Thanks a bunch, Eric, Brian, Stephanie, and Igalia! This is super helpful and already part of my toolkit.
BCD Watch originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/3uXNBlk
via IFTTT
Wednesday, September 25, 2024
Clear today!
With a high of F and a low of 50F. Currently, it's 63F and Clear outside.
Current wind speeds: 11 from the South
Pollen: 0
Sunrise: September 25, 2024 at 06:42PM
Sunset: September 26, 2024 at 06:42AM
UV index: 0
Humidity: 44%
via https://ift.tt/uRVXKg5
September 26, 2024 at 10:02AM
How to Make a “Scroll to Select” Form Control
The <select>
element is a fairly straightforward concept: focus on it to reveal a set of <option>
s that can be selected as the input’s value. That’s a great pattern and I’m not suggesting we change it. That said, I do enjoy poking at things and found an interesting way to turn a <select>
into a dial of sorts — where options are selected by scrolling them into position, not totally unlike a combination lock or iOS date pickers. Anyone who’s expanded a <select>
for selecting a country knows how painfully long lists can be and this could be one way to prevent that.
Here’s what I’m talking about:
It’s fairly common knowledge that styling <select>
in CSS is not the easiest thing in the world. But here’s the trick: we’re not working with <select> at all. No, we’re not going to do anything like building our own <select> by jamming a bunch of JavaScript into a <div>
. We’re still working with semantic form controls, only it’s radio buttons.
<section class=scroll-container>
<label for="madrid" class="scroll-item">
Madrid
<abbr>MAD</abbr>
<input id="madrid" type="radio" name="items">
</label>
<label for="malta" class="scroll-item">
Malta
<abbr>MLA</abbr>
<input id="malta" type="radio" name="items">
</label>
<!-- etc. -->
</section>
What we need is to style the list of selectable controls where we are capable of managing their sizes and spacing in CSS. I’ve gone with a group of labels with nested radio boxes as far as the markup goes. The exact styling is totally up to you, of course, but you can use these base styles I wrote up if you want a starting point.
.scroll-container {
/* SIZING & LAYOUT */
--itemHeight: 60px;
--itemGap: 10px;
--containerHeight: calc((var(--itemHeight) * 7) + (var(--itemGap) * 6));
width: 400px;
height: var(--containerHeight);
align-items: center;
row-gap: var(--itemGap);
border-radius: 4px;
/* PAINT */
--topBit: calc((var(--containerHeight) - var(--itemHeight))/2);
--footBit: calc((var(--containerHeight) + var(--itemHeight))/2);
background: linear-gradient(
rgb(254 251 240),
rgb(254 251 240) var(--topBit),
rgb(229 50 34 / .5) var(--topBit),
rgb(229 50 34 / .5) var(--footBit),
rgb(254 251 240)
var(--footBit));
box-shadow: 0 0 10px #eee;
}
A couple of details on this:
--itemHeight
is the height of each item in the list.--itemGap
is meant to be the space between two items.- The
--containerHeight
variable is the .scroll-container’s height. It’s the sum of the item sizes and the gaps between them, ensuring that we display, at maximum, seven items at once. (An odd number of items gives us a nice balance where the selected item is directly in the vertical center of the list). - The background is a striped gradient that highlights the middle area, i.e., the location of the currently selected item.
- The
--topBit
and –-footBit
variables are color stops that visually paint in the middle area (which is orange in the demo) to represent the currently selected item.
I’ll arrange the controls in a vertical column with flexbox declared on the .scroll-container:
.scroll-container {
display: flex;
flex-direction: column;
/* rest of styles */
}
With layout work done, we can focus on the scrolling part of this. If you haven’t worked with CSS Scroll Snapping before, it’s a convenient way to direct a container’s scrolling behavior. For example, we can tell the .scroll-container
that we want to enable scrolling in the vertical direction. That way, it’s possible to scroll to the rest of the items that are not in view.
.scroll-container {
overflow-y: scroll;
/* rest of styles */
}
Next, we reach for the scroll-snap-style
property that can be used to tell the .scroll-container
that we want scrolling to stop on an item — not near an item, but directly on it.
.scroll-container {
overflow-y: scroll;
scroll-snap-type: y mandatory;
/* rest of styles */
}
Now items “snap” onto an item instead of allowing a scroll to end wherever it wants. One more little detail I like to include is overscroll-behavior
, specifically along the y-axis as far as this demo goes:
.scroll-container {
overflow-y: scroll;
scroll-snap-type: y mandatory;
overscroll-behavior-y: none;
/* rest of styles */
}
overscroll-behavior-y: none
isn’t required to make this work, but when someone scrolls through the .scroll-container
(along the y-axis), scrolling stops once the boundary is reached, and any further continued scrolling action will not trigger scrolling in any nearby scroll containers. Just a form of defensive CSS.
Time to move to the items inside the scroll container. But before we go there, here are some base styles for the items themselves that you can use as a starting point:
.scroll-item {
/* SIZING & LAYOUT */
width: 90%;
box-sizing: border-box;
padding-inline: 20px;
border-radius: inherit;
/* PAINT & FONT */
background: linear-gradient(to right, rgb(242 194 66), rgb(235 122 51));
box-shadow: 0 0 4px rgb(235 122 51);
font: 16pt/var(--itemHeight) system-ui;
color: #fff;
input { appearance: none; }
abbr { float: right; } /* The airport code */
}
As I mentioned earlier, the --itemHeight
variable is setting as the size of each item and we’re declaring it on the flex
property — flex: 0 0 var(--itemHeight)
. Margin is added before and after the first and last items, respectively, so that every item can reach the middle of the container through scrolling.
The scroll-snap-align
property is there to give the .scroll-container
a snap point for the items. A center alignment, for instance, snaps an item’s center (vertical center, in this case) with the .scroll-container
‘s center (vertical center as well). Since the items are meant to be selected through scrolling alone pointer-events: none
is added to prevent selection from clicks.
One last little styling detail is to set a new background on an item when it is in a :checked
state:
.scroll-item {
/* Same styles as before */
/* If input="radio" is :checked */
&:has(:checked) {
background: rgb(229 50 34);
}
}
But wait! You’re probably wondering how in the world an item can be :checked
when we’re removing pointer-events
. Good question! We’re all finished with styling, so let’s move on to figuring some way to “select” an item purely through scrolling. In other words, whatever item scrolls into view and “snaps” into the container’s vertical center needs to behave like a typical form control selection. Yes, we’ll need JavaScript for that.
let observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
with(entry) if(isIntersecting) target.children[1].checked = true;
});
}, {
root: document.querySelector(`.scroll-container`), rootMargin: `-51% 0px -49% 0px`
});
document.querySelectorAll(`.scroll-item`).forEach(item => observer.observe(item));
The IntersectionObserver
object is used to monitor (or “observe”) if and when an element (called a target
) crosses through (or “intersects”) another element. That other element could be the viewport itself, but in this case, we’re observing the .scroll-container
for when a .scroll-item
intersects it. We’ve established the observed boundary with rootMargin:"-51% 0px -49% 0px"
.
A callback function is executed when that happens, and we can use that to apply changes to the target element, which is the currently selected .scroll-item
. In our case, we want to select a .scroll-item
that is at the halfway mark in the .scroll-container
: target.children[1].checked = true
.
That completes the code. Now, as we scroll through the items, whichever one snaps into the center position is the selected item. Here’s a look at the final demo again:
Let’s say that, instead of selecting an item that snaps into the .scroll-container
‘s vertical center, the selection point we need to watch is the top of the container. No worries! All we do is update the scroll-snap-align
property value from center to start in the CSS and remove the :first-of-type
‘s top margin. From there, it’s only a matter of updating the scroll container’s background gradient so that the color stops highlight the top instead of the center. Like this:
And if one of the items has to be pre-selected when the page loads, we can get its position in JavaScript (getBoundingClientRect()
) and use the scrollTo()
method to scroll the container to where that specific item’s position is at the point of selection (which we’ll say is the center in keeping with our original demo). We’ll append a .selecte
d class on that .scroll-item
.
<section class="scroll-container">
<!-- more items -->
<label class="scroll-items selected">
2024
<input type=radio name=items />
</label>
<!-- more items -->
</section>
Let’s select the .selected
class, get its dimensions, and automatically scroll to it on page load:
let selected_item = (document.querySelector(".selected")).getBoundingClientRect();
let scroll_container = document.querySelector(".scroll-container");
scroll_container.scrollTo(0, selected_item.top - scroll_container.offsetHeight - selected_item.height);
It’s a little tough to demo this in a typical CodePen embed, so here’s a live demo in a GitHub Page (source code). I’ll drop a video in as well:
That’s it! You can build up this control or use it as a starting point to experiment with different layouts, styles, animations, and such. It’s important the UX clearly conveys to the users how the selection is done and which item is currently selected. And if I was doing this in a production environment, I’d want to make sure there’s a good fallback experience for when JavaScript might be unavailable and that my markup performs well on a screen reader.
References and further reading
- A Few Functional Uses for Intersection Observer to Know When an Element is in View (Preethi Sam)
- An Explanation of How the Intersection Observer Watches (Travis Almand)
- Practical CSS Scroll Snapping (Max Kohler)
- The Current State of Styling Selects in 2019 (Chris Coyier)
- CSS Flexbox Layout Guide (CSS-Tricks)
- CSS flex property (CSS-Tricks)
- CSS Scroll Snap Properties (MDN)
- scrollTo() (MDN)
How to Make a “Scroll to Select” Form Control originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/GBPDqX5
via IFTTT
Tuesday, September 24, 2024
Clear today!
With a high of F and a low of 49F. Currently, it's 57F and Clear outside.
Current wind speeds: 3 from the Southwest
Pollen: 0
Sunrise: September 24, 2024 at 06:41PM
Sunset: September 25, 2024 at 06:44AM
UV index: 0
Humidity: 52%
via https://ift.tt/IcjVing
September 25, 2024 at 10:02AM
Color Mixing With Animation Composition
Mixing colors in CSS is pretty much a solved deal, thanks to the more recent color-mix()
function as it gains support. Pass in two color values — any two color values at all — and optionally set the proportions.
background-color: color-mix(#000 30%, #fff 70%);
We also have the relative color syntax that can manipulate colors from one color space to another and modify them from there. The preeminent use case being a way to add opacity to color values that don’t support it, such as named colors.
background-color: hsl(from black h s l); /* hsl(0 0% 0%) */
background-color: hsl(from black h s l / 50%); /* hsl(0 0% 0% / 50%) */
We can get hacky and overlay one opaque element with another, I suppose.
Same general idea maybe, but with mix-blend-mode
?
Another roundabout way of getting there is something I saw this morning when looking over the updates that Ryan added to the animation
property in the Almanac. Now, we all know that animation
is shorthand for about a gajillion other properties (the order of which always eludes me). One of those is animation-composition
and it’s used to… well, Ryan nails the explanation:
Defining a property in CSS also sets what is considered the underlying value of the property. By default, keyframe animations will ignore the underlying value, as they only consider the effect values defined within the animation. Keyframes create a stack of effect values, which determines the order in which the animation renders to the browser. Composite operations are how CSS handles the underlying effect combined with the keyframe effect value.
Manuel Matuzović and Robin Rendle also have excellent ways of explaining the property, the former of which sparked us to update the Almanac.
OK! We have three values supported by animation-composition
to replace
the underlying property value in favor of the effect value defined in keyframes, add
to them, or accumulate
for combining multiple values. The add
value is what’s interesting to us because… oh gosh, let’s just let Ryan take it:
[I]nstead of replacing an underlying
background-color
property value with the keyframe’s effect value, the color type values are combined, creating new colors.
A-ha! The example goes like this:
See that? The add
value blends the two colors as one transitions to the other. Notice, too, how much smoother that transition is than the replace
value, although we wind up with a completely new color at the 100% mark rather than the color we declared in the keyframes. What if we pause the animation at some arbitrary point? Can we extract a new color value from it?
Ryan made this so that hovering on the elements pauses the animation. If we crack open DevTools and force the :hover
pseudo on the element, maybe we can head over to the Computed tab to get the new color value.
Interestingly, we get some RGB conversions in there. Probably because updating color channels is easier than converting one hex to another? Browsers do smart stuff.
Now I want to go update my old color interpolation demo…
Hmm, not any different to my untrained eye. Maybe that’s only because we’re changing the HSL’s hue channel and it’s super subtle. Whatever the case, animation-composition
can produce new computed color values. What you need those for and what you’d do with them? I dunno, but go wild.
Color Mixing With Animation Composition originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/JlysZVx
via IFTTT
Monday, September 23, 2024
Mostly Cloudy today!
With a high of F and a low of 51F. Currently, it's 60F and Fair outside.
Current wind speeds: 9 from the Southwest
Pollen: 0
Sunrise: September 23, 2024 at 06:40PM
Sunset: September 24, 2024 at 06:45AM
UV index: 0
Humidity: 52%
via https://ift.tt/sJzt9aT
September 24, 2024 at 10:02AM
The selectmenu Element is No More…Long Live select!
I was looking over an older article Patrick Brosset penned for us introducing <selectmenu>
, a new proposal at the time for a more style-able cousin to <select>
. From there, I clicked the linked-up <selectmenu>
explainer and got… this:
OK, link rot is a thing and happens all the time. Perhaps the site needs a little URL designing? But no, it’s not that at all. I searched a bit and found Jared White’s post saying that <selectmenu>
is no more, which came by way of Una’s post over at the Chrome Developer Blog seeking feedback on a “customizable select”. And Adam Argyle’s got a wonderful demo dedicated to it, no surprise there.
I’m only sharing the links for now but plan to spend some time with it and jot down notes on Open UI’s new page for the Customizable <select>
. I enjoyed looking at the boilerplate from Adam’s demo as a first glance:
select {
&, &::picker(select) {
appearance: base-select;
}
&::picker(select) {
transition:
display allow-discrete 1s,
opacity 1s,
overlay 1s allow-discrete
;
}
&:not(:open)::picker(select) {
opacity: 0;
}
&:open::picker(select) {
opacity: 1;
@starting-style {
opacity: 0;
}
}
}
I see the ::picker(select)
there that’s driving all of it. If I sneak a peek at Una’s post, I see that there are more ways to select different <select>
parts, including:
<selectedoption>
(the current selection)<option>
(which now accepts HTML in between the tags!)option::before
option:checked
(a little confusion here with the selected option)
<button>
(the little chevron arrow marker thingy)
So, perhaps Chrome is more of a fan of extending the native <select>
with additional CSS features for selecting the existing parts rather than moving forward with a completely new element. That’s cool, as one of Una’s demos shows how we still get the default <select>
behavior even if a browser does not support the new selectors.
The selectmenu Element is No More…Long Live select! originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/KznRop3
via IFTTT
Mostly Clear today!
With a high of F and a low of 15F. Currently, it's 14F and Clear outside. Current wind speeds: 13 from the Southwest Pollen: 0 S...
-
So you want an auto-playing looping video without sound? In popular vernacular this is the very meaning of the word GIF . The word has stuck...
-
With a high of F and a low of 31F. Currently, it's 37F and Cloudy outside. Current wind speeds: 7 from the Northeast Pollen: 0 S...
-
Last year , we kicked out a roundup of published surveys, research, and other findings from around the web. There were some nice nuggets in ...