Polymer CSS ::content selector not working - javascript

I haven't used Polymer since version 0.5 so I decided to give it a shot again. I've been having some trouble with the :host and ::content selectors, especially given I found that the :host selector only works when my style tag is placed outside the tag.
Anyway, my problem is that I cannot get the host selector to work unless I specify display: block in my CSS under :host. Second, apparently there isn't a difference between the selectors ":host" and ":host ::content". I'm trying to ONLY style content which is inserted into the content tag without using a wrapper element.
Here is my code from custom-element.html:
<dom-module id="custom-element">
<style>
/* Demonstrating how to specify inserted content
any content added here is styled
*/
:host ::content
{
color: green;
}
/* This CSS targets the custom-element tag itself */
:host
{
padding: 4px;
background-color: gray;
}
</style>
<template>
<!-- Title will be placed here before the content -->
<h2 id="title">{{title}}</h2>
<!-- Any content inside the tag will be placed here -->
<content></content>
</template>
....
And here is the relevant location where it is used in index.html:
<!-- Auto-binding templates -->
<template id="t" is="dom-bind">
<h1>Your input was <span>{{inputValue}}</span></h1>
<br>
<input is="iron-input" bind-value="{{inputValue}}">
<input type="button" value="Add to list" onClick="pushItem()">
<ul>
<!-- Repeating templates -->
<!-- Here, the items attribute specifies the array of items to bind to. -->
<template id="repeatingList" is="dom-repeat" items="{{listItems}}">
<!-- This demonstrates that we can find the index and data for every item in the specified array -->
<li>Array index <span>{{index}}</span>- <span>{{item}}</span></li>
</template>
</ul>
<br>
<custom-element title="{{inputValue}}"><p>Lorem ipsum!</p></custom-element>
</template>
Here's how it appears (the gray background doesn't appear behind the element content and the color should only be applied to the content tag): https://goo.gl/photos/p2EjTSjySCh2srY78

From https://www.polymer-project.org/1.0/docs/devguide/styling.html#styling-distributed-children-content
You must have a selector to the left of the ::content pseudo-element

Your shadow DOM styles should be inside your <template> tag.
::content doesn't directly map to an element and so styles applied directly to it will be ignored. Instead it allows you to override styles inside the content.
So:
:host { background-color: gray; } /* Styles <custom-element> */
:host ::content { color: green; } /* Does nothing */
:host ::content > p { color: green; } /* Overrides the <p>Lorem ipsum!</p> to be green */
Finally note that <custom-element> has no default styles at all of its own - it only has what you specify in :host. For any visual components you'll find that you just about always need to specify display in the :host.

Related

How to changing a style in node_modules in its own vue <style> tags

I want to make changes to the css file inside the multiselect package. But I don't want to change it from within node_modules, all I want is to write it between style tags of my page that I created with vue. I want to change the white-space property But I can't see any change when I write as below. Can you help with this?
Default.css (Node_modules)
.multiselect-tag {
align-items: center;
background: var(--ms-tag-bg,#10b981);
border-radius: var(--ms-tag-radius,4px);
color: var(--ms-tag-color,#fff);
white-space: nowrap;
}
My template
<template>
<div class="filters">
<Multiselect
class="multiselect"
v-model="value"
mode="tags"
placeholder="Customer"
:close-on-select="false"
:filter-results="false"
/>
</div>
</template>
My CSS code
<style scoped>
.multiselect {
--ms-tag-bg: #dbeafe;
--ms-tag-color: #2563eb;
--ms-radius: 0.475rem;
--ms-dropdown-radius: 0.475rem;
--ms-spinner-color: #2563eb;
--ms-tag-ml: 0.85rem;
}
.multiselect,
.multiselect-tag {
white-space: normal !important;
}
</style>
I think you need to remove the scoped from your <style scoped> style tag, as this will let the styles only apply for the current component (and the root node of the child). But you want to style an element the Multiselect component.
<style>
.multiselect {
--ms-tag-bg: #dbeafe;
--ms-tag-color: #2563eb;
--ms-radius: 0.475rem;
--ms-dropdown-radius: 0.475rem;
--ms-spinner-color: #2563eb;
--ms-tag-ml: 0.85rem;
}
.multiselect,
.multiselect-tag {
white-space: normal !important;
}
</style>
Beware that removing the scoped will make the styles apply globally, so all Multiselect instances will be affected. If this is not what you need, you might try to use deep selectors.
See vue style docs.
Hope this helps.
So if I have got you right, you want to change / overwrite your default CSS from your stylesheet with new values in your hmtl.
To do this, simply insert "style" within your tag.
For example:
<Multiselect class="multiselect" style="color: black;"/>

css display none on specific page, without page id

I'd like to hide a column in css for only one specific page and i saw several options for it, but every one uses page id. What if two pages have the same id and the differences are only in the class definitions?
I want to use the 'display none' tag only on /Page 2/.
Here is the example:
/Page1/
<body id="body" class="bootstrap-body page-body home_body body-admin-logged" role="document">
/Page 2/
<body id="body" class="bootstrap-body page-body list_page_body category_list_body body-pathway-top body-admin-logged" role="document">
/Column - Page2/
The html code
<aside class="col-md-3 col-sm-12 col-xs-12 column-left">
/Column-Page2/ css code
.column-content-left, .column-left {
float: left;
}
If I use the display none in the css above, it will works perfectly. The problem is that it reflects on /Page1/ too.
Is it possible to do that in css or javascript, without accessing the html?
You can select the body css too like this:
body.list_page_body .column-content-left, body.list_page_body .column-left {
display: none;
}
This should only trigger for the body with the class .list_page_body (or you can use another class specific to that page.
Use a class unique to the second page, for example list_page_body and in your css
.list_page_body .column-content-left, .list_page_body .column-left
{
display:none;
}
It is possible in javascript. Just get the url of the page using window.location.href and add a class or something if it's the page you want the special treatment on.
The classes that distinguish page 2 from page one are: list_page_body category_list_body and body-pathway-top. So you can use any of them to implement your CSS on page 2 without effecting page 1.
Example:
body.category_list_body .column-left{
display:none;
}
You can do it with jQuery by aiming the url path
jQuery(function ($){
var pathname = window.location.pathname;
if (pathname == "/page2/"){
$(".column-class").css("display","none");
}
})
If page 2's body tag has a unique class, you can use the .parent .child {} CSS selector. From what you've provided:
body.list_page_body .column-content-left, body.list_page_body .column-content-left {
display: none;
}
Just so you know, with parent / child selectors, you can use either .parent .child or .parent > .child. The former would select all instances within .parent that the .child class is used in the document:
<body class="parent">
<div class="child">
<div class="child">
</div>
</div>
</body>
In the example above, .parent .child {} would apply rules to both the initial .child as well as the nested .child.
The latter .parent > .child applies to only direct descendants. Using the same example above, only the initial .child element would be selected by .parent > .child. The nested .child wouldn't be affected.

Paper ripple does not fire

I have this code as a custom element:
<link rel="import" href="../paper-ripple/paper-ripple.html">
<polymer-element name="menu-item">
<template>
<style>
:host {
box-sizing: border-box;
position: absolute;
font-size: 16px;
width:100%;
}
.center{
text-align: center;
}
</style>
<div class="item">
<div class="content center" fit>
<content select="*"></content>
</div>
<paper-ripple fit></paper-ripple>
</div>
</template>
<script>
Polymer({
});
</script>
It is instantiated as follows: <menu-item>Home</menu-item>
Problem is, either the ripple fires and the link does not.
Or the link fires but the ripple does not.
How should I be doing this?
Thanks,
g3
I think the basic problem is that the way you have it structured, the anchor tag and the paper-ripple are siblings, so there's no way for the click event to bubble up from the ripple to the anchor, or vice versa.
One approach would be to have the anchor tag inside your element and use data binding, like so:
<div class="item">
<a href="{{url}}">
<div class="content center" fit>
{{text}}
</div>
<paper-ripple fit></paper-ripple>
</a>
</div>
...
<menu-item url="{{url('#/')}}" text="Home"></menu-item>
Full demo here:
http://jsbin.com/bumiva/3/edit
Another approach would be to use your original structure and add a click listener on the outer <div> and follow the link manually, like this:
http://jsbin.com/wadiwu/2/edit
Hope this helps.
I was able to get it to work by changing your code to create the element to have the anchor tags around the element, like so:
<menu-item>site</menu-item>
removing select="*" from your content element, and giving your :host style some height. I set mine to height: 32px;

Styling content inserted in the Shadow DOM

I have this example:
http://codepen.io/dbugger/pen/IuDxw
Where I have an insertion point inside the Shadow DOM and I try to apply an style to it, making it disappear. But the image is still visible. I suspect there is some principle I haven't undestood propely from the Web Components.
Can someone explain me what am I doing wrong?
The trick is that the image is not, as kkemple mentioned, part of the Shadow DOM, but rather the Light DOM, which means it's not directly accessible from inside the component. It's user provided content, like the parameters passed into a class constructor in an OOP language. If at all possible, then, the user should provide their own styles to go with it.
That being said, there are definitely valid use cases where the component author wants to style user-provided content. Hiding certain parts of the user-provided markup based on attributes on the host, events (clicks), etc. is definitely one of those. In that case, wrap the <content> element in a Shadow DOM element and hide that:
<template>
<style>
.image {
display: none;
}
</style>
<div class="image">
<content></content>
</div>
</template>
http://codepen.io/anon/pen/rCGqD
On a side note: It is technically possible to apply styles directly to Light DOM elements, but be aware that in many cases this is considered leaking implementation details to the outside world. If the first solution works, use that instead.
It is not working is because your code is not in the shadow DOM, the div and image is still accessible through default styling. I forked your codepen and added the styling so you could see.
var host = document.querySelector(".host");
var template = document.getElementById( 'template' );
var root = host.webkitCreateShadowRoot();
root.appendChild( template.content );
<template id="template">
<style>
.wrapper {
display: none;
}
</style>
<div class="wrapper">
<content selector=".img"></content>
</div>
<h2>In the Shadows</h2>
</template>
<style>
img {
border: 1px solid black;
}
</style>
<div class="host">
<img class="img" src="http://placehold.it/200x275&text=1" alt="" />
</div>
http://codepen.io/kkemple/pen/euBKs
I didn't go in to why it was not creating a shadow DOM element as your JS looked correct to me but here is a great article on shadow DOM web-ponents:
http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom/

Use of Pseudo-Elements in Polymer.js

I'm taking my first steps with Polymer.js, and I'm struggling with creating a pseudo-element.
This is what I tried:
In my host document:
<style type="text/css">
#host::x-a-cool-test {
color: green;
}
</style>
<div id="host">
<my-custom-element></my-custom-element>
</div>
In my custom element:
<element name="my-custom-element">
<template>
<style>
#host {
* { display: block; color: blue; }
}
</style>
<div id="group" pseudo="x-a-cool-test">
just some text
</div>
</template>
<script>
Polymer.register(this);
</script>
</element>
That will show just my text in blue. That is correct, because according to this, rules wrapped in a #host have higher specificity than any selector in the parent page.
My question:
If I delete color: blue from inside the #host block in my template, the text is shown in black and NOT green as I would expect. Why is that???
I believe this plunker works how you want it to. Basically, the CSS pseudo-element has to be applied directly to the custom element (in this case the my-custom-element). I switched id="host" to it (instead of its parent div) and the code worked.
<div>
<my-custom-element id="host"></my-custom-element>
</div>
Note: The overriding nature of #host may change. Some (myself included) think it should be more for providing default, fallback styles. In this case rules in the host document will override #host rules instead of the other way around.

Categories