MONIMEGA
  • Blog
    • Politics
    • Software
    • Technology
    • Business
    • Design
    • Hardware
    • Health
    • Italy
    • Music
    • Sports
    • Strategy
    • World
  • Contatto
  • Galleria
  • Informazioni
  • Servizi
  • A New Book Cultivates a Rich Survey of 300 Magnificent Gardens

    A New Book Cultivates a Rich Survey of 300 Magnificent Gardens

    July 15, 2025
    Design

    A New Book Cultivates a Rich Survey of 300 Magnificent Gardens

    From the humble backyard plot to the royal Water Theatre Grove at Versailles, gardens have long been a source of sustenance, beauty, and spiritual communion. A forthcoming book from Phaidon sprouts from this history as it celebrates how these sites of joy and grandeur endure throughout the ages.

    The Contemporary Garden travels to 300 green spaces across 40 countries, surveying the everlasting link between horticulture, nature, and aesthetics. Included in its 300-plus pages are private and public spaces in a wide array of styles, from wild plots in urban centers to impeccably trimmed topiaries to designs that prize water features as much as foliage.

    a spread from the book 'The Contemporary Garden' with a photograph of Little Island in the Hudson River

    While the book peers into some gardens only accessible to a few, many of its pages highlight well-trodden areas open to the public, like New York’s elevated Little Island, designed by Heatherwick Studio. Perhaps unsurprisingly, several spaces also double as outdoor galleries—including the High Line in Manhattan—or are artworks themselves. In the latter category is Gabriel Orozco’s The Orozco Garden, which bridges sculpture and horticulture through intricately laid brickwork and overgrown grasses at South London Gallery.

    Bridging natural sciences with art and design, The Contemporary Garden showcases how, even in this increasingly digital age, green spaces continue to be one of humanity’s perennial fascinations.

    Slated for release in late September, The Contemporary Garden is available for pre-order in the Colossal Shop.

    a square garden with depression ponds
    Kim Wilkie for the 10th Duke of Buccleuch, Orpheus, Boughton House, Kettering, Northamptonshire, England, 2009. Photo by Kim Wilkie
    a spread from the book 'The Contemporary Garden' with a photograph of a colorful landscape composition
    a aerial view of a lush garden with a pond
    Louis Benech and Jean-Michel Othoniel, Water Theatre Grove, Château de Versailles, Versailles, France (2015). Photo © EPV/Thomas Garnier
    a wood walkway through a green forest with scaffolding made of branches
    Dominique and Benoît Delomez, Jardin intérieur à ciel ouvert, Athis-de-l’Orne, Normandy, France, (2000–11). Photo courtesy of Benoît and Dominique Delomez
    a white building with circular trimmed trees in the background with a stream flowing in the foreground
    Erik Dhont, Bonemhoeve, Damme, West Flanders, Belgium, (2005). Photo © Jean-Pierre Gabriel
    a largely tile and stone garden in a courtyard
    Gabriel Orozco, The Orozco Garden, South London Gallery, London, England, (2016). Photo by Andy Stagg
    the cover of 'The Contemporary Garden'

    Do stories and artists like this matter to you? Become a Colossal Member today and support independent arts publishing for as little as $7 per month. The article A New Book Cultivates a Rich Survey of 300 Magnificent Gardens appeared first on Colossal.


    Source: Colossal.

  • From chaos to clarity: Using GitHub Copilot agents to improve developer workflows

    July 15, 2025
    Software

    Modern development often starts with good intentions: a quick script, a prototype, maybe an action to automate one small thing. But as projects evolve, those early efforts can become brittle. What if you could bring clarity and structure to those projects without slowing down your momentum?

    This tutorial shows how we used GitHub Copilot coding agent to refactor and enhance a personal GitHub Actions project called validate-file-exists. What started as a patchwork utility became well-structured, test-covered, documented, and set up for success with Copilot agent mode and coding agent.

    We’ll walk through my example of:

    • Updating Copilot custom instructions for better task alignment.
    • Creating the copilot-setup-steps.yaml file to give the coding agent the needed tools in its environment.
    • Working with Copilot to identify technical debt.
    • Collaborating with Copilot in pull requests.
    • Partnering with Copilot to iteratively improve the UI on a separate project.

    The GitHub Action that started it all

    Back in November 2024, I created a small GitHub Action called validate-file-exists. I wanted to ensure certain files (like a dependabot.yml file, or .github/copilot-instructions.md) were present in a repository. If not, then the GitHub Actions workflow would fail. It supported comma-separated inputs and was meant to be part of a larger “baseline” of quality gates I use across projects.

    It was functional, but I could have improved it further. It was missing docs, had inconsistent metadata, some gaps in input validation, and didn’t have Copilot custom instructions or Copilot setup steps to help set Copilot up for success. Time to fix that—with help from Copilot agent mode in VS Code.

    Step one: Improve custom instructions

    Before bringing in the agent, I reviewed the existing copilot-instructions.md. It was sparse, without any description of the repository’s purpose, usage, or structure, nor any clear guidance for Copilot.

    Action:

    I based the instructions on best practices for using Copilot to work on tasks, by providing the sample custom instructions file in my prompt, and asking Copilot to update based on the codebase. In other words, I wanted it to provide: 

    • A clear summary of the repository/codebase and what the action does.
    • Contribution guidelines (how to build, format, lint, and test the codebase, including expectations before committing).
    • Project structure overview.
    • Key technical principles (strict TypeScript, incorporating TSDoc, and focused and manageable functions).

    Result: 

    Copilot had the right context on my expectations to guide it toward meaningful contributions. You can find the latest version here, but here’s a snapshot below:

    # Validate File Exists Action
    
    This is a TypeScript-based GitHub Action that validates whether specified files
    exist in a repository. It takes a comma-separated list of files and validates
    their existence, failing the workflow if any files are missing. Please follow
    these guidelines when contributing:
    
    ## Code Standards
    
    ### Required Before Each Commit
    
    - Run `npm run format:write` to ensure consistent code formatting with Prettier
    - Run `npm run lint` to check for ESLint violations
    - Run `npm run test` to ensure all tests pass
    - Run `npm run local-action` to test the action locally with a `.env` file
    
    ### Development Flow
    
    - Build: `npm run package` (compiles TypeScript and bundles with ncc)
    - Test: `npm run test` or `npm run ci-test`
    - Coverage: `npm run coverage` (generates coverage badge)
    - Full check: `npm run all` (format, lint, test, coverage, package)
    - Local testing: `npm run local-action` (test action locally with .env file)
    
    ## Repository Structure
    
    - `src/`: Core TypeScript source code
      - `main.ts`: Main entry point and action orchestration
      - `fileValidator.ts`: Core file validation logic
      - `index.ts`: Action entrypoint that calls run()
      - `types.ts`: TypeScript type definitions
    - `__tests__/`: Jest unit tests for all source files
    - `dist/`: Compiled and bundled JavaScript output (generated)
    - `action.yml`: GitHub Action metadata and interface definition
    - `script/`: Release automation scripts
    - `badges/`: Generated coverage and status badges
    
    ## Key Guidelines
    
    1. Follow TypeScript strict mode and best practices
    1. Use clear, descriptive variable and function names
    1. Add TSDoc comments for all public methods and classes
    1. Write comprehensive unit tests using Jest for all new functionality
    1. Keep functions focused and manageable (generally under 50 lines)
    1. Use consistent error handling with @actions/core.setFailed()
    1. Validate inputs and provide meaningful error messages
    1. Use @actions/core for all GitHub Actions integrations (inputs, outputs,
       logging)
    1. Maintain backwards compatibility for action inputs/outputs

    Step two: Add copilot-setup-steps.yaml

    Like any of us developers, Copilot coding agent needs a proper environment to work. That means setting up any required frameworks, installing dependencies, and making sure Copilot has access to the right tools to get the job done.

    Action:

    I created .github/copilot-setup-steps.yaml using the GitHub docs on customizing the development environment for Copilot coding agent. The example checks out the code, sets up Node.js, and installs the needed dependencies. Given this is a TypeScript action, that’s pretty much all I needed!

    I made one minor change to the workflow: changing the node-version to be sourced from the .node-version file, to be consistent with my CI workflow: 

    - name: Setup Node.js
    id: setup-node
    uses: actions/setup-node@v4
    with:
    node-version-file: .node-version
    cache: npm

    Result:

    Copilot coding agent has the needed dependencies and tools to build, lint, and test the codebase. As it makes changes to the codebase, it will be able to check for quality (as requested in our custom instructions) using the tools that were installed in the copilot-setup-steps.yml.

    Step three: Let Copilot find technical debt

    With the setup steps and custom instructions in place, it was time to find a task. So of course, I turned to Copilot. Using Copilot Chat in VS Code, we asked Copilot:

    “What technical debt exists in this project? Please give me a prioritized list of areas we need to focus on. I would like to create a GitHub Issue with the top 2 or 3 items. Please include a brief problem statement, a set of acceptance criteria, and pointers on what files need to be added/updated.”

    Within minutes, it explored the codebase and came back with a list of suggestions:

    • Inconsistent package metadata.
    • README mismatches (wrong input names).
    • No validation for empty or malformed inputs.

    Notice how we asked for a problem statement, acceptance criteria, and guidance on the files to add/update? These come from the best practices for using Copilot to work on tasks. In other words, make sure your issues are well-scoped!

    Action:

    I asked Copilot to write an issue that addresses those three items. Once I created the issue, I assigned it to Copilot.

    Step four: Copilot coding agent in action

    Once assigned, the agent kicked off a new pull request. Here’s what it did, asynchronously:

    • Explored the contents of the repository to build up its understanding of the problem.
    • Created a plan based on its exploration.
    • Fixed the package.json name, description, URLs, and author field.
    • Updated the README usage examples to match the code.
    • Added input validation logic:
      • Reject empty or whitespace-only strings.
      • Reject inputs that are just commas.
    • Wrote four new tests for these edge cases.
    • Confirmed linting, formatting, and coverage were intact.
    • Updated the pull request body with a checklist of work completed.

    As I delegated the task to Copilot, it freed me up to explain to the audience what it was doing, and how the Copilot setup steps and instructions work in the context of the agent’s session.

    Result:

    Copilot completed all tasks in just over 11 minutes. After a review of the agent’s approach, I approved the CI workflow so that it could run the standard quality checks on the codebase. The workflow failed, but through no fault of Copilot. I had some additional Markdown linting checks in the CI that weren’t in the instructions.

    Real-time debugging and linting fixes

    While I could have fixed it manually, it was a good opportunity to show how we can iterate on changes with Copilot. I added a new comment to the pull request, and asked Copilot: 

    “Our GitHub Action had a linting error for the markdown, can you fix that please?” (Also pasting the error from the GitHub Actions workflow.)

    A few minutes later, it updated the code, pushed a new commit, and the pull request passed. And while Copilot was working on my task in the background, I was able to wrap up the stream.

    Bonus: Making UI changes with Copilot coding agent and the Playwright MCP server

    While Copilot worked on the initial code changes for the GitHub Action, I showed off a second project: a Trend Radar visualisation app (here’s the repository) that I built using Next.js and Tailwind CSS.

    Problem:

    Users had to manually input point data into forms. I wanted to:

    • Let users click on the radar to place a point.
    • Enable drag-and-drop repositioning to change a point’s category or likelihood. 

    Solution:

    I filed a GitHub issue describing the UX, acceptance criteria, and references.

    After a few iterations of comments by working through the pull request, Copilot coding agent:

    • Implemented click-to-place logic.
    • Added drag-and-drop support.
    • Wrote unit tests.
    • Took screenshots and attached them to the pull request.
    • Updated the pull request (and responded with comments) with summaries of the work that had been completed

    Playwright is now installed by default with the Copilot coding agent, which lets Copilot validate visual behaviors too.

    Final thoughts

    This wasn’t just a cleanup session. It was a lesson in modern software collaboration. Copilot coding agent is our new teammate.

    By structuring our repositories with context and intent, we invite Copilot to contribute meaningfully.

    If you haven’t tried Copilot coding agent yet, think through your existing projects:

    • Clean up an old GitHub Action.
    • Refactor a neglected repository.
    • Add validations and tests.

    You might be surprised how much progress you can make in an afternoon.

    • Write clear, concise copilot-instructions.md to steer the agent.
    • Use copilot-setup-steps.yaml to give the agent the tools it needs.
    • Setting a clear and well-scoped piece of work is important when working with Copilot.
    • Copilot now has access to a browser, thanks to the Playwright MCP server – enabling it to interact with web pages, and add screenshots to the pull request.
    • You don’t have to work on new projects to try out Copilot and its agentic capabilities. Which existing project could you get started on?

    Ready to explore more? See how the GitHub billing team uses the coding agent to continuously burn down technical debt >

    The post From chaos to clarity: Using GitHub Copilot agents to improve developer workflows appeared first on The GitHub Blog.


    Source: The GitHub Blog.

  • Cognition Buys Windsurf, Nvidia Can Sell to China, Grok 4 and Kimi

    July 15, 2025
    Strategy

    Cognition rescues Windsurf, Nvidia can sell H20s to China, and Grok 4 and Kimi K2 point to future avenues of model improvement


    Source: Stratechery by Ben Thompson.

  • CachyOS Now Lets Users Choose Their Shell

    July 14, 2025
    Software

    CachyOS Now Lets Users Choose Their Shell » Linux Magazine

    CachyOS is a bit niche and not nearly as well-known as the likes of Ubuntu or Fedora, but sometimes those niche distributions do things that might inspire the others to follow suit.

    In a recent announcement for the upcoming July CachyOS release, the developers announced that the user’s shell can be chosen during installation. Before you get too excited, the choices are limited to fish, Zsh, and Bash. During installation, if you don’t choose between fish or Zsh, Bash will be chosen for you (even though the default configuration will remain fish).

    There are other changes coming to the next iteration of CachyOS, such as KDE Plasma installations defaulting to Wayland. At the same time, the Nvidia legacy drivers and plasma-x11-session will also be installed to avoid problems.

    Plus, CachyOS also offers improved latency, thanks to mesa-git now including the upstream merge request for Anti-Lag 2. Proton-CachyOS will also include support for Anti-Lag 2 as well.

    Finally, CachyOS has dropped support for cachy-browser in favor of cachyos-firefox-settings, which can be applied on top of a standard Firefox installation.

    You can read all about the upcoming changes in this official CachyOS blog.
     
     



     
     
     


    Source: Linux Magazine News (path: lmi_news).

  • Code review in the age of AI: Why developers will always own the merge button

    July 14, 2025
    Software

    When GitHub first shipped the pull request (PR) back in 2008, it wrapped a plain-text diff in a social workflow: comments, approvals, and a merge button that crucially refused to light up without at least one thumbs up from another developer. That design decision hard-wired accountability into modern software and let maintainers scale far beyond hallway conversations or e-mail patches.

    Seventeen years later, just about every “agentic” coding tool, from research demos to enterprise platforms, still funnels its work through that same merge gate. The PR remains the audit log, the governance layer, and the social contract that says nothing ships until a person is willing to own it.

    Now that large language models (LLM) can scaffold projects, file PRs, and even reply to review comments they wrote themselves, the obvious next question is, who is accountable for code that ships when part of it comes from a model? 

    At GitHub, we think the answer hasn’t fundamentally changed: it’s the developer who hits “Merge.” But what has changed is everything that happens before that click. 

    In this article, we’ll explore how we’re re-thinking code reviews for a world where developers increasingly work with AI (and how your team can, too). 

    What a code review is (still) for

    Before diving into AI-assisted reviews, it’s worth revisiting what makes code reviews effective in the first place. A review is far more than a bug hunt. A good review: 

    • Catches defects and security issues 
    • Ensures high code quality
    • Shares knowledge across the team and maintains consistency with your codebase’s patterns and standards
    • Safeguards long-term maintainability 

    AI changes none of that; it only moves the bottlenecks. A model can quickly spot an unused import, but it can’t decide if a new endpoint undermines your privacy stance or if today is the right day to pay down that gnarly abstraction you’ve been avoiding. The merge button still needs (and, in our view, always will need) a developer fingerprint.

    For a deeper dive into effective code review practices, check out our guide on reviewing code effectively.

    What we learned from GitHub Copilot’s code review capabilities

    Earlier this year, the GitHub Copilot code review team conducted in-depth interviews with developers about their code review process. They also walked us through their code review workflow. These interviews revealed three consistent patterns:

    1. No special treatment for AI: Reviewers grilled model-generated diffs as hard as those from other developers.
    2. Self reviews raised the floor: Developers who ran a Copilot review before opening a PR often wiped out an entire class of trivial nit-picks (i.e., trimmed imports, missing tests), cutting out back-and-forth by roughly a third.
    3. AI was no replacement for human judgement: Programming often involves trade-offs. LLMs can inform you about those trade-offs, but someone has to make the call about what path to take based on your organization’s goals and standards.  

    An overarching principle quickly became clear: AI augments developer judgment; it can’t replace it. And our findings, from confidence scores to red-flag explanations, are informing how we’re building Copilot’s code review features.

    GitHub Copilot code review is generally available

    Let an AI teammate handle the first pass. GitHub Copilot’s code-review agent is generally available for every Copilot plan, and it’s spotting bugs, performance issues, and even suggesting fixes before a human ever opens the diff. Enable automatic reviews in your repo rules or ask Copilot on-demand, right inside GitHub, GitHub Mobile, or VS Code.

    Learn more >

    What AI can (and can’t) handle today

    LLMs are already great at the “grind” layer of a review:

    • Mechanical scanning. “Is there a typo?” “Are all arguments used?”
    • Pattern matching. “This looks like SQL injection” or “You forgot to await that promise.”
    • Pedantic consistency. “Variable names snake_case here, camelCase there.”

    Soon they’ll be able to do even more, such as understand product and domain context.  But they still fall short on:

    • Architecture and trade-offs. Should we split this service? Cache locally?
    • Mentorship. Explaining why a pattern matters and when to break it.
    • Values. Should we build this feature at all?

    Those gaps keep developers in the loop and in the pilot’s seat. That principle is foundational for us as we continue to develop GitHub Copilot. 

    A playbook for modern code reviews

    The most effective approach to AI-assisted code reviews starts before you even submit your pull request. Think of it as the golden rule of development: Treat code reviewers the way you’d like them to treat you.

    Use AI to self review your code in your IDE

    Before pushing your code, run GitHub Copilot code review in your IDE to catch the obvious stuff so your teammates can focus on the nuanced issues that require developer insight. Copilot code review can comb your staged diff, suggest docstrings, and flag null dereferences. From there, you can fix everything it finds before you submit your PR so teammates never see the noise.

    Take ownership of your code

    Just because you used AI to generate code doesn’t mean it’s not your code. Once you commit code, you’re responsible for it. That means understanding what it does, ensuring it follows your team’s standards, and making sure it integrates well with the rest of your codebase.

    If an AI agent writes code, it’s on me to clean it up before my name shows up in git blame.

    Jon Wiggins, Machine Learning Engineer at Respondology

    Run your code through automated CI gates

    Your pipeline should already be running unit tests, secret scanning, CodeQL, dependency checks, style linters. Keep doing that. Fail fast, fail loudly.

    Practical tips for personal code hygiene:

    • Review your own code in your IDE.
    • Ensure variable names, comments, and structure to match your team’s conventions.
    • Test AI-generated code thoroughly before including it in pull requests.

    Use AI to focus on the areas where your judgement is critical

    The real power of AI in code reviews isn’t in replacing developers as the reviewers. It’s in handling the routine work that can bog down the review process, freeing developers to focus where their judgment is most valuable.

    AI doesn’t replace your existing automated checks. 

    Make sure tests pass, coverage metrics are met, and static analysis tools have done their work before developer reviews begin. This creates a solid foundation for more meaningful discussion. 

    You can use an LLM to catch not just syntax issues, but also patterns, potential bugs, and style inconsistencies. Ironically, LLMs are particularly good at catching the sorts of mistakes that LLMs make, which is increasingly relevant as more AI-generated code enters our codebases.

    Clearly define roles

    Set clear expectations about when AI feedback should be considered versus when human judgment takes precedence. For example, you should rely on other developers for code architecture and consistency with business goals and organizational values. It’s especially useful to use AI to review long repetitive PRs where it can be easy to miss little things.

    Implementation tips for building a sustainable AI-assisted review process

    • Document clear guidelines that specify when to use AI in code reviews, what types of feedback to trust, and how to escalate when developers disagree with an AI code review. With GitHub Copilot, for instance, you can use custom instructions to set clear rules for how Copilot engages with your code. 
    • Update guidelines regularly based on team feedback and evolving AI capabilities. Remember that as your codebase and AI tools evolve, what works today might not work tomorrow.
    • Encourage open team discussions about the strengths and limitations of AI-assisted reviews. Share both positive and negative experiences to help everyone learn and improve their approach.
    • Refine automation continuously by using feedback from reviewers to improve your automated testing strategy. Identify patterns where solutions to recurring issues could be automated.

    Developer judgement remains crucial

    While AI can handle much of the routine work in code reviews, developer judgment remains irreplaceable for architectural decisions, mentoring and knowledge transfer, and context-specific decisions that require understanding of your product and users. 

    And even as LLMs get smarter, three review tasks remain stubbornly human:

    1. Architecture trade-offs: Should we split this service? Cache locally? Pay tech debt now or later?
    2. Mentorship and culture: PR threads are team classrooms. A bot can’t tell a junior engineer the war story behind that odd regex.
    3. Ethics and product values: “Should we even build this?” is a question AI can’t answer.

    The goal is to make developers more effective by letting them focus on what they do best.

    Learn more about code reviews with GitHub Copilot > 

    The post Code review in the age of AI: Why developers will always own the merge button appeared first on The GitHub Blog.


    Source: The GitHub Blog.

  • Design Patterns For AI Interfaces

    Design Patterns For AI Interfaces

    July 14, 2025
    Software

    So you need to design a new AI feature for your product. How would you start? How do you design flows and interactions? And how do you ensure that that new feature doesn’t get abandoned by users after a few runs?

    In this article, I’d love to share a very simple but systematic approach to how I think about designing AI experiences. Hopefully, it will help you get a bit more clarity about how to get started.

    This article is part of our ongoing series on UX. You can find more details on design patterns and UX strategy in Smart Interface Design Patterns 🍣 — with live UX training coming up soon. Jump to table of contents.

    The Receding Role of AI Chat

    One of the key recent shifts is a slow move away from traditional “chat-alike” AI interfaces. As Luke Wroblewski wrote, when agents can use multiple tools, call other agents and run in the background, users orchestrate AI work more — there’s a lot less chatting back and forth.

    In fact, chatbots are rarely a great experience paradigm — mostly because the burden of articulating intent efficiently lies on the user. But in practice, it’s remarkably difficult to do well and very time-consuming.

    Chat doesn’t go away, of course, but it’s being complemented with task-oriented UIs — temperature controls, knobs, sliders, buttons, semantic spreadsheets, infinite canvases — with AI providing predefined options, presets, and templates.

    There, AI emphasizes the work, the plan, the tasks — the outcome, instead of the chat input. The results are experiences that truly amplify value for users by sprinkling a bit of AI in places where it delivers real value to real users.

    To design better AI experiences, we need to study 5 key areas that we need to shape.

    Input UX: Expressing Intent

    Conversational AI is a very slow way of helping users express and articulate their intent. Usability tests show that users often get lost in editing, reviewing, typing, and re-typing. It’s painfully slow, often taking 30-60 seconds for input.

    As it turns out, people have a hard time expressing their intent well. In fact, instead of writing prompts manually, it’s a good idea to ask AI to write a prompt to feed itself.

    With Flora AI, users can still write prompts, but they visualize their intent with nodes by connecting various sources visually. Instead of elaborately explaining to AI how we need the pipeline to work, we attach nodes and commands on a canvas.

    With input for AI, being precise is slow and challenging. Instead, we can abstract away the object we want to manipulate, and give AI precise input by moving that abstracted object on a canvas. That’s what Krea.ai does.

    In summary, we can minimize the burden of typing prompts manually — with AI-generated pre-prompts, prompt extensions, query builders, and also voice input.

    Output UX: Displaying Outcomes

    AI output doesn’t have to be merely plain text or a list of bullet points. It must be helpful to drive people to insights, faster. For example, we could visualize output by creating additional explanations based on the user’s goal and motivations.

    For example, Amelia Wattenberger visualized AI output for her text editor PenPal by adding style lenses to explore the content from. The output could be visualized in sentence lengths and scales Sad — Happy, Concrete — Abstract, and so on.

    The outcome could also be visualized on a map, which, of course, is expected for an AI GIS analyst. Also, users can access individual data layers, turn them on and off, and hence explore the data on the map.

    We can also use forced ranking and prioritizations to suggest best options and avoid choice paralysis — even if a user asks for top 10 recommendations. We can think about ways to present results as a data table, or a dashboard, or a visualization on a map, or as a structured JSON file, for example.

    Refinement UX: Tweaking Output

    Users often need to cherry-pick some bits from the AI output and bring them together in a new place — and often they need to expand on one section, synthesize bits from another section, or just refine the outcome to meet their needs.

    Refinement is usually the most painful part of the experience, with many fine details being left to users to explain elaborately. But we can use good old-fashioned UI controls like knobs, sliders, buttons, and so on to improve that experience, similar to how Adobe Firefly does it (image above).

    We can also use presets, bookmarks, and allow users to highlight specific parts of the outcome that they’d like to change — with contextual prompts acting on highlighted parts of the output, rather than global prompts.

    AI Actions: Tasks To Complete

    With AI agents, we can now also allow users to initiate tasks that AI can perform on their behalf, such as scheduling events, planning, and deep research. We could also ask to sort results or filter them in a specific way.

    But we can also add features to help users use AI output better — e.g., by visualizing it, making it shareable, allowing transformations between formats, or also posting to Slack, Jira, and so on.

    AI Integration: Where Work Happens

    Many AI interactions are locked within a specific product, but good AI experiences happen where the actual work happens. It would be quite unusual to expect a dedicated section for Autocomplete, for example, but we do so for AI features.

    The actual boost in productivity comes when users rely on AI as a co-pilot or little helper in the tools they use daily for work. It’s seamless integrations into Slack, Teams, Jira, GitHub, and so on — the tools that people use anyway. Dia Browser and Dovetail are great examples of it in action.

    Wrapping Up

    Along these five areas, we can explore ways to minimize the cost of interaction with a textbox, and allow users to interact with the points of interest directly, by tapping, clicking, selecting, highlighting, and bookmarking.

    Many products are obsessed with being AI-first. But you might be way better off by being AI-second instead. The difference is that we focus on user needs and sprinkle a bit of AI across customer journeys where it actually adds value.

    And AI products don’t have to be AI-only. There is a lot of value in mapping into the mental models that people have adopted over the years, and enhance them with AI, similar to how we do it with browsers’ autofill, rather than leaving users in front of a frightening and omnipresent text box.

    Useful Resources

    • Where Should AI Sit In Your UI?, by Sharang Sharma
    • Shape of AI: Design Patterns, by Emily Campbell
    • AI UX Patterns, by Luke Bennis
    • Design Patterns For Trust With AI, via Sarah Gold
    • AI Guidebook Design Patterns, by Google
    • Usable Chat Interfaces to AI Models, by Luke Wroblewski
    • The Receding Role of AI Chat, by Luke Wroblewski
    • Agent Management Interface Patterns, by Luke Wroblewski
    • Designing for AI Engineers, by Eve Weinberg

    Meet “Smart Interface Design Patterns”

    You can find more details on design patterns and UX in Smart Interface Design Patterns, our 15h-video course with 100s of practical examples from real-life projects — with a live UX training later this year. Everything from mega-dropdowns to complex enterprise tables — with 5 new segments added every year. Jump to a free preview. Use code BIRDIE to save 15% off.

    Meet Smart Interface Design Patterns, our video course on interface design & UX.


    • Video + UX Training
    • Video only

    Video + UX Training

    $ 495.00 $ 699.00

    Get Video + UX Training

    25 video lessons (15h) + Live UX Training.
    100 days money-back-guarantee.

    Video only

    $ 300.00$ 395.00


    Get the video course

    40 video lessons (15h). Updated yearly.
    Also available as a UX Bundle with 2 video courses.


    Source: Articles on Smashing Magazine — For Web Designers And Developers.

  • Google and Windsurf, Stinky Deals, Chesterton’s Fence and the Silicon Valley Ecosystem

    July 14, 2025
    Strategy

    Windsurf’s founders and IP are going to Google in the latest stinky deal that is downstream of regulator’s recklessly messing the startup ecosystem.


    Source: Stratechery by Ben Thompson.

  • Setting Line Length in CSS (and Fitting Text to a Container)

    July 14, 2025
    Software

    First, what is line length? Line length is the length of a container that holds a body of multi-line text. “Multi-line” is the key part here, because text becomes less readable if the beginning of a line of text is too far away from the end of the prior line of text. This causes users to reread lines by mistake, and generally get lost while reading.

    Luckily, the Web Content Accessibility Guidelines (WCAG) gives us a pretty hard rule to follow: no more than 80 characters on a line (40 if the language is Chinese, Japanese, or Korean), which is super easy to implement using character (ch) units:

    width: 80ch;

    The width of 1ch is equal to the width of the number 0 in your chosen font, so the exact width depends on the font.

    Setting the optimal line length

    Just because you’re allowed up to 80 characters on a line, it doesn’t mean that you have to aim for that number. A study by the Baymard Institute revealed that a line length of 50-75 characters is the optimal length — this takes into consideration that smaller line lengths mean more lines and, therefore, more opportunities for users to make reading mistakes.

    That being said, we also have responsive design to think about, so setting a minimum width (e.g., min-width: 50ch) isn’t a good idea because you’re unlikely to fit 50 characters on a line with, for example, a screen/window size that is 320 pixels wide. So, there’s a bit of nuance involved, and the best way to handle that is by combining the clamp() and min() functions:

    • clamp(): Set a fluid value that’s relative to a container using percentage, viewport, or container query units, but with minimum and maximum constraints.
    • min(): Set the smallest value from a list of comma-separated values.

    Let’s start with min(). One of the arguments is 93.75vw. Assuming that the container extends across the whole viewport, this’d equal 300px when the viewport width is 320px (allowing for 20px of spacing to be distributed as you see fit) and 1350px when the viewport width is 1440px. However, for as long as the other argument (50ch) is the smallest of the two values, that’s the value that min() will resolve to.

    min(93.75vw, 50ch);

    Next is clamp(), which accepts three arguments in the following order: the minimum, preferred, and maximum values. This is how we’ll set the line length.

    For the minimum, you’d plug in your min() function, which sets the 50ch line length but only conditionally. For the maximum, I suggest 75ch, as mentioned before. The preferred value is totally up to you — this will be the width of your container when not hitting the minimum or maximum.

    width: clamp(min(93.75vw, 50ch), 70vw, 75ch);

    In addition, you can use min(), max(), and calc() in any of those arguments to add further nuance.

    If the container feels too narrow, then the font-size might be too large. If it feels too wide, then the font-size might be too small.

    Fit text to container (with JavaScript)

    You know that design trend where text is made to fit the width of a container? Typically, to utilize as much of the available space as possible? You’ll often see it applied to headings on marketing pages and blog posts. Well, Chris wrote about it back in 2018, rounding up several ways to achieve the effect with JavaScript or jQuery, unfortunately with limitations. However, the ending reveals that you can just use SVG as long as you know the viewBox values, and I actually have a trick for getting them.

    Although it still requires 3-5 lines of JavaScript, it’s the shortest method I’ve found. It also slides into HTML and CSS perfectly, particularly since the SVG inherits many CSS properties (including the color, thanks to fill: currentColor):

    CodePen Embed Fallback
    <h1 class="container">
      <svg>
        <text>Fit text to container</text>
      </svg>
    </h1>
    h1.container {
      /* Container size */
      width: 100%;
    
      /* Type styles (<text> will inherit most of them) */
      font: 900 1em system-ui;
      color: hsl(43 74% 3%);
    
      text {
        /*
          We have to use fill: instead of color: here
          But we can use currentColor to inherit the color
        */
        fill: currentColor;
      }
    }
    /* Select all SVGs */
    const svg = document.querySelectorAll("svg");
    
    /* Loop all SVGs */
    svg.forEach(element => {
      /* Get bounding box of <text> element */
      const bbox = element.querySelector("text").getBBox();
      /* Apply bounding box values to SVG element as viewBox */
      element.setAttribute("viewBox", [bbox.x, bbox.y, bbox.width, bbox.height].join(" "));
    });

    Fit text to container (pure CSS)

    If you’re hell-bent on a pure-CSS method, you are in luck. However, despite the insane things that we can do with CSS these days, Roman Komarov’s fit-to-width hack is a bit complicated (albeit rather impressive). Here’s the gist of it:

    • The text is duplicated a couple of times (although hidden accessibly with aria-hidden and hidden literally with visibility: hidden) so that we can do math with the hidden ones, and then apply the result to the visible one.
    • Using container queries/container query units, the math involves dividing the inline size of the text by the inline size of the container to get a scaling factor, which we then use on the visible text’s font-size to make it grow or shrink.
    • To make the scaling factor unitless, we use the tan(atan2()) type-casting trick.
    • Certain custom properties must be registered using the @property at-rule (otherwise they don’t work as intended).
    • The final font-size value utilizes clamp() to set minimum and maximum font sizes, but these are optional.
    <span class="text-fit">
      <span>
        <span class="text-fit">
          <span><span>fit-to-width text</span></span>
          <span aria-hidden="true">fit-to-width text</span>
        </span>
      </span>
      <span aria-hidden="true">fit-to-width text</span>
    </span>
    .text-fit {
      display: flex;
      container-type: inline-size;
    
      --captured-length: initial;
      --support-sentinel: var(--captured-length, 9999px);
    
      & > [aria-hidden] {
        visibility: hidden;
      }
    
      & > :not([aria-hidden]) {
        flex-grow: 1;
        container-type: inline-size;
    
        --captured-length: 100cqi;
        --available-space: var(--captured-length);
    
        & > * {
          --support-sentinel: inherit;
          --captured-length: 100cqi;
          --ratio: tan(
            atan2(
              var(--available-space),
              var(--available-space) - var(--captured-length)
            )
          );
          --font-size: clamp(
            1em,
            1em * var(--ratio),
            var(--max-font-size, infinity * 1px) - var(--support-sentinel)
          );
          inline-size: var(--available-space);
    
          &:not(.text-fit) {
            display: block;
            font-size: var(--font-size);
    
            @container (inline-size > 0) {
              white-space: nowrap;
            }
          }
    
          /* Necessary for variable fonts that use optical sizing */
          &.text-fit {
            --captured-length2: var(--font-size);
            font-variation-settings: "opsz" tan(atan2(var(--captured-length2), 1px));
          }
        }
      }
    }
    
    @property --captured-length {
      syntax: "<length>";
      initial-value: 0px;
      inherits: true;
    }
    
    @property --captured-length2 {
      syntax: "<length>";
      initial-value: 0px;
      inherits: true;
    }
    CodePen Embed Fallback

    Watch for new text-grow/text-shrink properties

    To make fitting text to a container possible in just one line of CSS, a number of solutions have been discussed. The favored solution seems to be two new text-grow and text-shrink properties. Personally, I don’t think we need two different properties. In fact, I prefer the simpler alternative, font-size: fit-width, but since text-grow and text-shrink are already on the table (Chrome intends to prototype and you can track it), let’s take a look at how they could work.

    The first thing that you need to know is that, as proposed, the text-grow and text-shrink properties can apply to multiple lines of wrapped text within a container, and that’s huge because we can’t do that with my JavaScript technique or Roman’s CSS technique (where each line needs to have its own container).

    Both have the same syntax, and you’ll need to use both if you want to allow both growing and shrinking:

    text-grow: <fit-target> <fit-method>? <length>?;
    text-shrink: <fit-target> <fit-method>? <length>?;
    • <fit-target>
      • per-line: For text-grow, lines of text shorter than the container will grow to fit it. For text-shrink, lines of text longer than the container will shrink to fit it.
      • consistent: For text-grow, the shortest line will grow to fit the container while all other lines grow by the same scaling factor. For text-shrink, the longest line will shrink to fit the container while all other lines shrink by the same scaling factor.
    • <fit-method> (optional)
      • scale: Scale the glyphs instead of changing the font-size.
      • scale-inline: Scale the glyphs instead of changing the font-size, but only horizontally.
      • font-size: Grow or shrink the font size accordingly. (I don’t know what the default value would be, but I imagine this would be it.)
      • letter-spacing: The letter spacing will grow/shrink instead of the font-size.
    • <length> (optional): The maximum font size for text-grow or minimum font size for text-shrink.

    Again, I think I prefer the font-size: fit-width approach as this would grow and shrink all lines to fit the container in just one line of CSS. The above proposal does way more than I want it to, and there are already a number of roadblocks to overcome (many of which are accessibility-related). That’s just me, though, and I’d be curious to know your thoughts in the comments.

    Conclusion

    It’s easier to set line length with CSS now than it was a few years ago. Now we have character units, clamp() and min() (and max() and calc() if you wanted to throw those in too), and wacky things that we can do with SVGs and CSS to fit text to a container. It does look like text-grow and text-shrink (or an equivalent solution) are what we truly need though, at least in some scenarios.

    Until we get there, this is a good time to weigh-in, which you can do by adding your feedback, tests, and use-cases to the GitHub issue.


    Setting Line Length in CSS (and Fitting Text to a Container) originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.


    Source: CSS-Tricks.

  • Scroll-Driven Sticky Heading

    July 11, 2025
    Software

    Scroll-driven animations are great! They’re a powerful tool that lets developers tie the movement and transformation of elements directly to the user’s scroll position. This technique opens up new ways to create interactive experiences, cuing images to appear, text to glide across the stage, and backgrounds to subtly shift. Used thoughtfully, scroll-driven animations (SDA) can make your website feel more dynamic, engaging, and responsive.

    A few weeks back, I was playing around with scroll-driven animations, just searching for all sorts of random things you could do with it. That’s when I came up with the idea to animate the text of the main heading (h1) and, using SDA, change the heading itself based on the user’s scroll position on the page. In this article, we’re going to break down that idea and rebuild it step by step. This is the general direction we’ll be heading in, which looks better in full screen and viewed in a Chromium browser:

    CodePen Embed Fallback

    It’s important to note that the effect in this example only works in browsers that support scroll-driven animations. Where SDA isn’t supported, there’s a proper fallback to static headings. From an accessibility perspective, if the browser has reduced motion enabled or if the page is being accessed with assistive technology, the effect is disabled and the user gets all the content in a fully semantic and accessible way.

    Just a quick note: this approach does rely on a few “magic numbers” for the keyframes, which we’ll talk about later on. While they’re surprisingly responsive, this method is really best suited for static content, and it’s not ideal for highly dynamic websites.

    Closer Look at the Animation

    Before we dive into scroll-driven animations, let’s take a minute to look at the text animation itself, and how it actually works. This is based on an idea I had a few years back when I wanted to create a typewriter effect. At the time, most of the methods I found involved animating the element’s width, required using a monospace font, or a solid color background. None of which really worked for me. So I looked for a way to animate the content itself, and the solution was, as it often is, in pseudo-elements.

    CodePen Embed Fallback

    Pseudo-elements have a content property, and you can (kind of) animate that text. It’s not exactly animation, but you can change the content dynamically. The cool part is that the only thing that changes is the text itself, no other tricks required.

    Start With a Solid Foundation

    Now that you know the trick behind the text animation, let’s see how to combine it with a scroll-driven animation, and make sure we have a solid, accessible fallback as well.

    We’ll start with some basic semantic markup. I’ll wrap everything in a main element, with individual sections inside. Each section gets its own heading and content, like text and images. For this example, I’ve set up four sections, each with a bit of text and some images, all about Primary Colors.

    <main>
      <section>
        <h1>Primary Colors</h1>
        <p>The three primary colors (red, blue, and yellow) form the basis of all other colors on the color wheel. Mixing them in different combinations produces a wide array of hues.</p>
        <img src="./colors.jpg" alt="...image description">
      </section>
      
      <section>
        <h2>Red Power</h2>
        <p>Red is a bold and vibrant color, symbolizing energy, passion, and warmth. It easily attracts attention and is often linked with strong emotions.</p>
        <img src="./red.jpg" alt="...image description">
      </section>
      
      <section>
        <h2>Blue Calm</h2>
        <p>Blue is a calm and cool color, representing tranquility, stability, and trust. It evokes images of the sky and sea, creating a peaceful mood.</p>
        <img src="./blue.jpg" alt="...image description">
      </section>
      
      <section>
        <h2>Yellow Joy</h2>
        <p>Yellow is a bright and cheerful color, standing for light, optimism, and creativity. It is highly visible and brings a sense of happiness and hope.</p>
        <img src="./yellow.jpg" alt="...image description">
      </section>
    </main>

    As for the styling, I’m not doing anything special at this stage, just the basics. I changed the font and adjusted the text and heading sizes, set up the display for the main and the sections, and fixed the image sizes with object-fit.

    CodePen Embed Fallback

    So, at this point, we have a simple site with static, semantic, and accessible content, which is great. Now the goal is to make sure it stays that way as we start adding our effect.

    The Second First Heading

    We’ll start by adding another h1 element at the top of the main. This new element will serve as the placeholder for our animated text, updating according to the user’s scroll position. And yes, I know there’s already an h1 in the first section; that’s fine and we’ll address it in a moment so that only one is accessible at a time.

    <h1 class="scrollDrivenHeading" aria-hidden="true">Primary Colors</h1>

    Notice that I’ve added aria-hidden="true" to this heading, so it won’t be picked up by screen readers. Now I can add a class specifically for screen readers, .srOnly, to all the other headings. This way, anyone viewing the content “normally” will see only the animated heading, while assistive technology users will get the regular, static semantic headings.

    CodePen Embed Fallback

    Note: The style for the .srOnly class is based on “Inclusively Hidden” by Scott O’Hara.

    Handling Support

    As much as accessibility matters, there’s another concern we need to keep in mind: support. CSS Scroll-Driven Animations are fantastic, but they’re still not fully supported everywhere. That’s why it’s important to provide the static version for browsers that don’t support SDA.

    The first step is to hide the animated heading we just added using display: none. Then, we’ll add a new @supports block to check for SDA support. Inside that block, where SDA is supported, we can change back the display for the heading.

    The .srOnly class should also move into the @supports block, since we only want it to apply when the effect is active, not when it’s not supported. This way, just like with assistive technology, anyone visiting the page in a browser without SDA support will still get the static content.

    .scrollDrivenHeading {
      display: none;
    }
    
    @supports (animation-timeline: scroll()) {
      .scrollDrivenHeading {
        display: block;
      }
      
      /* Screen Readers Only */
      .srOnly {
        clip: rect(0 0 0 0); 
        clip-path: inset(50%);
        height: 1px;
        overflow: hidden;
        position: absolute;
        white-space: nowrap; 
        width: 1px;
      }
    }

    Get Sticky

    The next thing we need to do is handle the stickiness of the heading. To make sure the heading always stays on screen, we’ll set its position to sticky with top: 0 so it sticks to the top of the viewport.

    While we’re at it, let’s add some basic styling, including a background so the text doesn’t blend with whatever’s behind the heading, a bit of padding for spacing, and white-space: nowrap to keep the heading on a single line.

    /* inside the @supports block */
    .scrollDrivenHeading {
      display: block;
      position: sticky;
      top: 0;
      background-image: linear-gradient(0deg, transparent, black 1em);
      padding: 0.5em 0.25em;
      white-space: nowrap;
    }

    Now everything’s set up: in normal conditions, we’ll see a single sticky heading at the top of the page. And if someone uses assistive technology or a browser that doesn’t support SDA, they’ll still get the regular static content.

    CodePen Embed Fallback

    Now we’re ready to start animating the text. Almost…

    The Magic Numbers

    To build the text animation, we need to know exactly where the text should change. With SDA, scrolling basically becomes our timeline, and we have to determine the exact points on that timeline to trigger the animation.

    To make this easier, and to help you pinpoint those positions, I’ve prepared the following script:

    @property --scroll-position {
      syntax: "<number>";
      inherits: false;
      initial-value: 0;
    }
    
    body::after {
      counter-reset: sp var(--scroll-position);
      content: counter(sp) "%";
      position: fixed;
      top: 0;
      left: 0;
      padding: 1em;
      background-color: maroon;
      animation: scrollPosition steps(100);
      animation-timeline: scroll();
    }
    
    @keyframes scrollPosition {
      0% { --scroll-position: 0; }
      100% { --scroll-position: 100; }
    }

    I don’t want to get too deep into this code, but the idea is to take the same scroll timeline we’ll use next to animate the text, and use it to animate a custom property (--scroll-position) from 0 to 100 based on the scroll progress, and display that value in the content.

    If we’ll add this at the start of our code, we’ll see a small red square in the top-left corner of the screen, showing the current scroll position as a percentage (to match the keyframes). This way, you can scroll to any section you want and easily mark the percentage where each heading should begin.

    CodePen Embed Fallback

    With this method and a bit of trial and error, I found that I want the headings to change at 30%, 60%, and 90%. So, how do we actually do it? Let’s start animating.

    Animating Text

    First, we’ll clear out the content inside the .scrollDrivenHeading element so it’s empty and ready for dynamic content. In the CSS, I’ll add a pseudo-element to the heading, which we’ll use to animate the text. We’ll give it empty content, set up the animation-name, and of course, assign the animation-timeline to scroll().

    And since I’m animating the content property, which is a discrete type, it doesn’t transition smoothly between values. It just jumps from one to the next. By setting the animation-timing-function property to step-end, I make sure each change happens exactly at the keyframe I define, so the text switches precisely where I want it to, instead of somewhere in between.

    .scrollDrivenHeading {
      /* style */
    
      &::after {
        content: '';
        animation-name: headingContent;
        animation-timing-function: step-end;
        animation-timeline: scroll();
      }
    }

    As for the keyframes, this part is pretty straightforward (for now). We’ll set the first frame (0%) to the first heading, and assign the other headings to the percentages we found earlier.

    @keyframes headingContent {
      0% { content: 'Primary Colors'}
      30% { content: 'Red Power'}
      60% { content: 'Blue Calm'}
      90%, 100% { content: 'Yellow Joy'}
    }

    So, now we’ve got a site with a sticky heading that updates as you scroll.

    CodePen Embed Fallback

    But wait, right now it just switches instantly. Where’s the animation?! Here’s where it gets interesting. Since we’re not using JavaScript or any string manipulation, we have to write the keyframes ourselves. The best approach is to start from the target heading you want to reach, and build backwards. So, if you want to animate between the first and second heading, it would look like this:

    @keyframes headingContent {
      0% { content: 'Primary Colors'}
      
      9% { content: 'Primary Color'}
      10% { content: 'Primary Colo'}
      11% { content: 'Primary Col'}
      12% { content: 'Primary Co'}
      13% { content: 'Primary C'}
      14% { content: 'Primary '}
      15% { content: 'Primary'}
      16% { content: 'Primar'}
      17% { content: 'Prima'}
      18% { content: 'Prim'}
      19% { content: 'Pri'}
      20% { content: 'Pr'}
      21% { content: 'P'}
      
      22% { content: 'R'}
      23% { content: 'Re'}
      24% { content: 'Red'}
      25% { content: 'Red '}
      26% { content: 'Red P'}
      27% { content: 'Red Po'}
      28%{ content: 'Red Pow'}
      29% { content: 'Red Powe'}
      
      30% { content: 'Red Power'}
      60% { content: 'Blue Calm'}
      90%, 100% { content: 'Yellow Joy'}
    }

    I simply went back by 1% each time, removing or adding a letter as needed. Note that in other cases, you might want to use a different step size, and not always 1%. For example, on longer headings with more words, you’ll probably want smaller steps.

    If we repeat this process for all the other headings, we’ll end up with a fully animated heading.

    CodePen Embed Fallback

    User Preferences

    We talked before about accessibility and making sure the content works well with assistive technology, but there’s one more thing you should keep in mind: prefers-reduced-motion. Even though this isn’t a strict WCAG requirement for this kind of animation, it can make a big difference for people with vestibular sensitivities, so it’s a good idea to offer a way to show the content without animations.

    If you want to provide a non-animated alternative, all you need to do is wrap your @supports block with a prefers-reduced-motion query:

    @media screen and (prefers-reduced-motion: no-preference) {
      @supports (animation-timeline: scroll()) {
        /* style */
      }
    }

    Leveling Up

    Let’s talk about variations. In the previous example, we animated the entire heading text, but we don’t have to do that. You can animate just the part you want, and use additional animations to enhance the effect and make things more interesting. For example, here I kept the text “Primary Color” fixed, and added a span after it that handles the animated text.

    <h1 class="scrollDrivenHeading" aria-hidden="true">
      Primary Color<span></span>
    </h1>

    And since I now have a separate span, I can also animate its color to match each value.

    CodePen Embed Fallback

    In the next example, I kept the text animation on the span, but instead of changing the text color, I added another scroll-driven animation on the heading itself to change its background color. This way, you can add as many animations as you want and change whatever you like.

    CodePen Embed Fallback

    Your Turn!

    CSS Scroll-Driven Animations are more than just a cool trick; they’re a game-changer that opens the door to a whole new world of web design. With just a bit of creativity, you can turn even the most ordinary pages into something interactive, memorable, and truly engaging. The possibilities really are endless, from subtle effects that enhance the user experience, to wild, animated transitions that make your site stand out.

    So, what would you build with scroll-driven animations? What would you create with this new superpower? Try it out, experiment, and if you come up with something cool, have some ideas, wild experiments, or even weird failures, I’d love to hear about them. I’m always excited to see what others come up with, so feel free to share your work, questions, or feedback below.


    Special thanks to Cristian Díaz for reviewing the examples, making sure everything is accessible, and contributing valuable advice and improvements.


    Scroll-Driven Sticky Heading originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.


    Source: CSS-Tricks.

  • The Layout Maestro Course

    July 11, 2025
    Software

    Layout. It’s one of those easy-to-learn, difficult-to-master things, like they say about playing bass. Not because it’s innately difficult to, say, place two elements next to each other, but because there are many, many ways to tackle it. And layout is one area of CSS that seems to evolve more than others, as we’ve seen in the past 10-ish years with the Flexbox, CSS Grid, Subgrid, and now Masonry to name but a few. May as well toss in Container Queries while we’re at it. And reading flow. And…

    That’s a good way to start talking about a new online course that Ahmad Shadeed is planning to release called The Layout Maestro. I love that name, by the way. It captures exactly how I think about working with layouts: orchestrating how and where things are arranged on a page. Layouts are rarely static these days. They are expected to adapt to the user’s context, not totally unlike a song changing keys.

    Ahmad is the perfect maestro to lead a course on layout, as he does more than most when it comes to experimenting with layout features and demonstrating practical use cases, as you may have already seen in his thorough and wildly popular interactive guides on Container Queries, grid areas, box alignment, and positioning (just to name a few).

    The course is still in development, but you can get a leg up and sign up to be notified by email when it’s ready. That’s literally all of the information I have at this point, but I still feel compelled to share it and encourage you to sign up for updates because I know few people more qualified to wax on about CSS layout than Ahmad and am nothing but confident that it will be great, worth the time, and worth the investment.

    I’m also learning that I have a really hard time typing “maestro” correctly. 🤓


    The Layout Maestro Course originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.


    Source: CSS-Tricks.

Previous Page
1 … 896 897 898 899 900 … 911
Next Page
MONIMEGA
  • Instagram
  • Facebook
  • Twitter
Gestisci Consenso
Per fornire le migliori esperienze, utilizziamo tecnologie come i cookie per memorizzare e/o accedere alle informazioni del dispositivo. Il consenso a queste tecnologie ci permetterà di elaborare dati come il comportamento di navigazione o ID unici su questo sito. Non acconsentire o ritirare il consenso può influire negativamente su alcune caratteristiche e funzioni.
Funzionale Always active
L'archiviazione tecnica o l'accesso sono strettamente necessari al fine legittimo di consentire l'uso di un servizio specifico esplicitamente richiesto dall'abbonato o dall'utente, o al solo scopo di effettuare la trasmissione di una comunicazione su una rete di comunicazione elettronica.
Preferenze
L'archiviazione tecnica o l'accesso sono necessari per lo scopo legittimo di memorizzare le preferenze che non sono richieste dall'abbonato o dall'utente.
Statistiche
L'archiviazione tecnica o l'accesso che viene utilizzato esclusivamente per scopi statistici. L'archiviazione tecnica o l'accesso che viene utilizzato esclusivamente per scopi statistici anonimi. Senza un mandato di comparizione, una conformità volontaria da parte del vostro Fornitore di Servizi Internet, o ulteriori registrazioni da parte di terzi, le informazioni memorizzate o recuperate per questo scopo da sole non possono di solito essere utilizzate per l'identificazione.
Marketing
L'archiviazione tecnica o l'accesso sono necessari per creare profili di utenti per inviare pubblicità, o per tracciare l'utente su un sito web o su diversi siti web per scopi di marketing simili.
  • Manage options
  • Manage services
  • Manage {vendor_count} vendors
  • Read more about these purposes
Visualizza le preferenze
  • {title}
  • {title}
  • {title}