惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

阮一峰的网络日志
阮一峰的网络日志
博客园 - 司徒正美
D
DataBreaches.Net
宝玉的分享
宝玉的分享
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 【当耐特】
人人都是产品经理
人人都是产品经理
博客园 - Franky
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
IT之家
IT之家
博客园 - 三生石上(FineUI控件)
J
Java Code Geeks
腾讯CDC
博客园_首页
The Cloudflare Blog
S
SegmentFault 最新的问题
C
Check Point Blog
美团技术团队
爱范儿
爱范儿
大猫的无限游戏
大猫的无限游戏
Hugging Face - Blog
Hugging Face - Blog
T
The Blog of Author Tim Ferriss
A
About on SuperTechFans
Blog — PlanetScale
Blog — PlanetScale

Hacker News

GitHub - SeanFDZ/macmind: Single-layer transformer in HyperTalk for the classic Macintosh Show HN: Agent-cache – Multi-tier LLM/tool/session caching for Valkey and Redis Bonsai 1-bit WebGPU - a Hugging Face Space by webml-community Moving a large-scale metrics pipeline from StatsD to OpenTelemetry / Prometheus GitHub - Nightmare-Eclipse/RedSun: The Red Sun vulnerability repository GitHub - SethPyle376/hiraeth: Local AWS emulator focused on fast integration testing, with SQS support, SQLite-backed state, and a debug-friendly web UI. GitHub - macOS26/Agent: Any AI, replaces Claude Code, Cursor, OpenClaw. Over 18 LLM providers (Claude, OpenAI, Gemini, Ollama, Zai, HF, Qwen) wired into a native Mac app that writes code, builds Xcode projects, bumps versions, manages git, automates Safari, use AppleScript, JS or Accessibility, extend Agent! w/ MCP Servers, run tasks from your iPhone via Messages. YouTube now lets you turn off Shorts I Made a Terminal Pager Burgers | マクドナルド公式 Commands — HackerNews CLI documentation ChatGPT for Excel PiCore - Raspberry Pi Port of Tiny Core Linux Live Nation illegally monopolized ticketing market, jury finds Google Broke Its Promise to Me. Now ICE Has My Data. Founding Engineer at Adaptional | Y Combinator CRISPR takes important step toward silencing Down syndrome’s extra chromosome GitHub - saffron-health/libretto: The AI toolkit for building reliable browser automations US v. Heppner (S.D.N.Y. 2026) no attorney-client privilege for AI chats [pdf] Retrofitting JIT Compilers into C Interpreters IPv6 – Google The Accursèd Alphabetical Clock Cybersecurity Looks Like Proof of Work Now Fragments: April 14 Cal.com Goes Closed Source: Why AI Security Is Forcing Our Decision | Cal.com - Scheduling Software for Online Bookings Laravel raised money and now injects ads directly into your agent When moving fast, talking is the first thing to break Too much Discussion of the XOR swap trick – Heather Cafe Introduction to Spherical Harmonics for Graphics Programmers The Grand Line
Phoenix LiveView 1.2 released! - Phoenix Blog
2026-06-14 · via Hacker News

LiveView 1.2.0 is available now!

To update from LiveView 1.1 to 1.2, simply update the version requirement in your mix.exs file and re-fetch your dependencies:

{:phoenix_live_view, "~> 1.2.0"}

Colocated CSS

In LiveView 1.1, we introduced Colocated Hooks and Colocated JavaScript, allowing you to write hooks directly inside any HEEx template. LiveView 1.2 builds on the background work done for Phoenix.LiveView.ColocatedJS to allow you to colocate CSS in HEEx too.

def table(assigns) do
  ~H"""
  <style :type={MyApp.ColocatedCSS}>
    thead {
      color: ...;
    }
    tbody, tr:hover {
      ...
    }
  </style>
  <table>...</table>
  """
end

As with Colocated JS, the :type attribute tells LiveView to extract the content of the tag at compile time into a special phoenix-colocated folder in your _build directory. This is then picked up by your bundler (usually Tailwind or Esbuild) and processed as part of your normal CSS pipeline.

That’s the easy part though. What you usually want when defining colocated styles is to scope them, such that they don’t accidentally apply to other elements on the page from different components. Modern CSS has a relatively new @scope rule, which allows us to do just that, with some caveats.

The @scope rule

@scope (scope root) to (scope limit) {
  /**/
}

The @scope rule accepts a root selector and an optional limit selector. If we are able to annotate the rendered HTML to include a unique attribute that identifies the “root” of a template and where it ends, we can have rules that only apply to that template. Since we control how HEEx compiles to HTML, we can do just that. Let’s look at an example:

attr :description, :string
slot :item

def my_list(assigns) do
  ~H"""
  <style :type={MyApp.ColocatedCSS}>
    p {
      font-weight: bold;
    }
  </style>

  <div>
    <p>{@description}</p>
    <ul>
      <li :for={item <- @item}>{render_slot(@item)}</li>
    </ul>
  </div>
  """
end

When we use this component in another template, like in your LiveView’s render/1 function,

<p>Hello World</p>
<.my_list description="My List">
  <:item>
    <p>Item 1</p>
  </:item>
  <:item>
    Item 2
  </:item>
</.my_list>

the unmodified rendered HTML would look something like this:

<p>Hello World</p>

<div>
  <p>My List</p>
  <ul>
    <li>
      <p>Item 1</p>
    </li>
    <li>
      Item 2
    </li>
  </ul>
</div>

Now, to properly identify the parts of the HTML that belong to the my_list component, we need to annotate the boundaries of all templates:

<p phx-r>Hello World</p>

<div phx-r phx-css-foo>
  <p>My List</p>
  <ul>
    <li>
      <p phx-r>Item 1</p>
    </li>
    <li>
      Item 2
    </li>
  </ul>
</div>

We use a special phx-r attribute which is added to all outermost elements of a template and which can be used as the limit selector in a @scope rule. Note that we used a slot in the example above. The <p>Item 1</p> does not belong to my_list‘s template, but to the caller instead. Therefore, it is also considered a “root” and gets a phx-r attribute. Then, because my_list uses scoped colocated CSS, its root elements (it only has a single one in this example) also get a unique phx-css-* attribute.

Combined, this allows us to write the following CSS:

@scope ([phx-css-foo]) to ([phx-r]) {
  p {
    font-weight: bold;
  }
}

With this rule, only p tags that belong to my_list‘s template will be rendered bold, while any other p tags on the page are unaffected.

LiveView does not automatically inject the phx-r attribute. Instead, it is opt-in with a new compile-time configuration:

config :phoenix_live_view,
  # the attribute set on all root tags. Used for Phoenix.LiveView.ColocatedCSS.
  root_tag_attribute: "phx-r"

When implementing colocated CSS, we stumbled across a problem that required us to revisit how HEEx templates are compiled. If you want to read more about this, we published a separate technical deep dive.

tl;dr: To make colocated CSS work, we had to change how we compile HEEx templates by splitting compilation into a separate tokenization and parsing step, allowing us to handle macro components (colocated CSS and JS) without making the rest of the compilation more complex. It also allowed us to reuse code we previously had to duplicate between template compilation and formatting.

We don’t ship scoping by default

With all that effort for colocated CSS, you might be startled when you hear that we don’t actually ship scoping in LiveView 1.2. The reason is that the @scope rule is not yet well supported across browsers at the time of writing (June 2026). Instead, we ship a @behaviour you can implement to do custom scoping, which also allows you to use different strategies. We do have the @scope implementation in the docs if you decide to be an early adopter.

Small improvements landing in 1.2

Apart from colocated CSS, LiveView 1.2 also includes some small improvements:

  • You can now implement a Phoenix.LiveView.HTMLFormatter.TagFormatter behaviour to format <script> and <style> tags in HEEx with a tool of your choice. We have an example using prettier in the documentation.
  • Phoenix.LiveView.JS structs are now automatically encoded when sent with push_event if you use either Jason or the built-in JSON module. You can also call JS.to_encodable/1 to encode them to a string yourself.
  • HEEx debug annotations can now be configured per module by setting the @debug_heex_annotations and @debug_attributes module attributes.
  • Test warnings can now be configured by category.
  • We now have separate documentation for the JavaScript client

and some more which can be found in the changelog.

If you have feedback, please don’t hesitate to post a thread on the Elixir forum or contact me on BlueSky. If you find any issues or bugs, please open up an issue.

Thank you to Dashbit for sponsoring this work!

Happy coding!

-Steffen