Polyfill ShadyCSS không xử lý CSS đúng cách trong Edge


8

Tôi đang xây dựng một tiện ích cho các trang web của bên thứ ba, sử dụng Shadow DOM để ngăn CSS của họ can thiệp vào trang web của chúng tôi. Tôi đang sử dụng các polyfill ShadyDOMShadyCSS để làm cho nó hoạt động trong Edge và IE, nhưng nó không chuyển đổi CSS cho DOM bóng tối như tôi mong đợi.

Thí dụ:

<!DOCTYPE html>
<html>
	<head>
		<title>Shadow DOM test</title>
	</head>
	<body>
		<div id="container">container is here</div>
		<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/2.3.0/webcomponents-bundle.js"></script>
		<script>
			const shadow = document.getElementById("container").attachShadow({ mode: "open" });
			const style = document.createElement("style");
			style.innerHTML = `
				:host .stuff {
					background: #ff00ff;
				}
			`;
			shadow.appendChild(style);
			const div = document.createElement("div");
			div.classList.add("stuff");
			div.innerHTML = "stuff inside shadow dom";
			shadow.appendChild(div);
		</script>
	</body>
</html>

Trong Chrome (hỗ trợ bóng DOM nguyên bản), stuffdiv có nền màu hồng, như tôi mong đợi. Nhưng trong Edge (vốn không hỗ trợ bóng DOM nguyên bản), tôi thấy văn bản "nội dung trong bóng tối" (nghĩa là tập lệnh của tôi đã chạy và các chức năng ShadyDOM hoạt động), nhưng tôi không thấy nền màu hồng.

Tại sao chuyện này đang xảy ra? Tôi đang đính kèm một gốc bóng tối với một div cũ đơn giản, thay vì sử dụng các yếu tố tùy chỉnh như ví dụ trong ShadyCSS README, nhưng điều đó có quan trọng không? Nếu vậy, làm thế nào tôi có thể làm cho công việc này? Tôi đang làm việc trên một ứng dụng lớn, hiện có và không muốn thực hiện quá nhiều thay đổi cùng một lúc, vì vậy tôi rất thích sử dụng các yếu tố HTML tiêu chuẩn mà tôi đang sử dụng ( divs, buttons, v.v.) thay vì đi kèm với các phần tử hoặc mẫu riêng , mặc dù tôi sẽ sẵn sàng xem xét các mẫu và / hoặc các phần tử tùy chỉnh nếu nó có thể được thực hiện dễ dàng, mà không phải thực hiện nhiều thay đổi lớn.


Tôi đã thử một vài điều, giống như phụ thêm các styleyếu tố trực tiếp đến khu vực nội divthay vì gốc rễ bóng, phụ thêm các styleyếu tố sau phụ bên trong div, và thiết lập innerHTMLcác styleyếu tố sau khi thêm nó. Nhưng không có những điều đó giúp được.
Elias Zamaria

Nếu tôi loại bỏ :hostkhỏi bộ chọn CSS, thì các kiểu sẽ được áp dụng. Nhưng chúng cũng được áp dụng cho những thứ bên ngoài gốc bóng tối mà tôi không muốn.
Elias Zamaria

Tôi cũng đã cố gắng những thứ như thế ShadyCSS.styleElement(element)ShadyCSS. styleSubtree(element)và họ đã không làm việc.
Elias Zamaria

Tôi đã có thể lấy polyfill để tạo kiểu cho một phần tử tùy chỉnh được tạo bằng một mẫu, nhưng tôi muốn tránh làm điều đó bởi vì làm điều đó trong ứng dụng của tôi sẽ yêu cầu thay đổi và nghiên cứu lại một loạt các thứ.
Elias Zamaria

Trong trường hợp điều này hữu ích với bất kỳ ai: ứng dụng của tôi sử dụng Preact. Tôi đang sử dụng một thành phần bậc cao hơn để tách CSS của chúng tôi khỏi CSS của bên thứ ba (điều này sẽ can thiệp vào CSS của chúng tôi theo nhiều cách). Nó hoạt động bằng cách đặt công cụ của chúng tôi vào iframe và thực hiện một số thủ thuật để đặt stylethẻ vào đúng vị trí và điều chỉnh kích thước phù hợp. Nó rất chậm trong việc kết xuất và xử lý cồng kềnh, vì vậy tôi đã thay đổi nó để sử dụng Shadow DOM. Bây giờ, nó hoạt động rất đẹp trong tất cả các trình duyệt không phải của Microsoft. Tôi đang cố gắng làm cho nó hoạt động trong Edge và IE bằng cách sử dụng polyfill, nhưng nó không hoạt động.
Elias Zamaria

Câu trả lời:


7

Với ShadyCSS

:host Phần tử giả CSS không được biết đến trong Edge.

Để làm cho nó hoạt động, bạn nên sử dụng ShadyCSS.prepareTemplate()nó sẽ thay thế: máy chủ lưu trữ theo tên của thành phần tùy chỉnh và xác định kiểu là kiểu toàn cầu sẽ áp dụng cho tất cả các trang.

Hãy nhớ rằng không có Shadow DOM trong Edge: không có ranh giới / phạm vi cho CSS với Shadow DOM giả / đa chức năng.

Trong trường hợp của bạn, bạn có thể sử dụng ShadyCSS.prepareTemplate( yourTemplate, 'div' )như trong ví dụ dưới đây:

ShadyCSS.prepareTemplate( tpl, 'div' )
container.attachShadow( { mode: "open" } )
         .appendChild( tpl.content.cloneNode(true) )
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/2.3.0/webcomponents-bundle.js"></script>

<template id=tpl>
    <style>
    :host .stuff {
       background: #ff00ff;
     }
     </style>
    <div class=stuff>stuff inside shadow dom</div>
</template>

<div id=container>container is here</div>

Lưu ý: vì polyfill sẽ thay thế: máy chủ lưu trữ bằng div và thêm nó dưới dạng toàn cục, bạn có thể quan sát một số tác dụng phụ nếu bạn có một phần mã HTML khác phù hợp div .stuff.


Không có ShadyCSS

ShadyCSS được thiết kế cho các yếu tố tùy chỉnh, nhưng không thực sự cho các yếu tố tiêu chuẩn. Tuy nhiên, bạn nên lấy cảm hứng từ polyfill và tạo rõ ràng các thuộc tính kiểu cho Shadow DOM giả (polyfill). Trong trường hợp của bạn thay thế :hostbằng div#containter:

container.attachShadow( { mode: "open" } )
         .appendChild( tpl.content.cloneNode(true) )
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/2.3.0/webcomponents-bundle.js"></script>

<template id=tpl>
    <style>
    div#container .stuff { 
       background: #ff00ff;
     }    
    :host .stuff {
       background: #ff00ff;
     }
     </style>
    <div class=stuff>stuff inside shadow dom</div>
</template>

<div id=container>container is here</div>


Cảm ơn vì sự trả lời. Tôi đang bận thử những ý tưởng của riêng tôi. Tôi sẽ thử của bạn và xem xét chấp nhận hoặc nâng cao câu trả lời của bạn, khi tôi có cơ hội, có lẽ sẽ có một thời gian vào ngày mai.
Elias Zamaria

Câu trả lời này đã giúp tôi rất nhiều cảm ơn!
calipoop

Điều đó có vẻ tốt, nhưng bất kỳ công cụ mẫu nào có thể được tạo ra (dễ dàng và thực tế) để hoạt động trong ứng dụng Preact (hoặc React) liên tục cố gắng thay đổi nội dung của các div (tại nhiều thời điểm, vì nhiều lý do)? Tôi sẽ cần phải làm cho nó bằng cách nào đó làm thay đổi DOM bóng đúng lúc, phải không?
Elias Zamaria

@EliasZamaria xin lỗi Tôi không phải là chuyên gia về React nhưng tôi biết một số người sử dụng nó với Shadow DOM (tức là github.com/Wildhoney/ReactShadow ). Tùy thuộc vào trường hợp sử dụng của bạn, có thể bạn sẽ cần sử dụng MutingObserver để phát hiện các thay đổi trên DOM.
Supersharp

@Supersharp cảm ơn câu trả lời của bạn. Các nhà quan sát đột biến trông rất tuyệt, nhưng tôi không nghĩ rằng đáng để nỗ lực sử dụng chúng cho trường hợp sử dụng của mình (giả lập bóng DOM đủ tốt cho 8% hoặc hơn người dùng của chúng tôi sử dụng Edge và IE).
Elias Zamaria
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.