-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use amp-elements for creating dynamic placeholders during buildCallback. #2846
Conversation
'left': '8px', | ||
'right': '8px', | ||
}); | ||
wrapper.appendChild(image); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Attribute placeholder
should be set somewhere here :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
So, I definitely think this looks better, especially if we specifically focus on a separate RE: YouTube |
Sounds good. I'll do some more refinement here and try to get this to work for most cases. For YouTube should we just use the As for But either case we can make this clear in our life-cycle docs that this is optionally gets called depending on whether we are able to detect a placeholder exists already at that time or not. Let me do some more work on this to get a good visual result out of it and see if we can take it from there. |
I'm totally ok if we continue "the old way" with YouTube and much more interested in us reaching out to them to discuss and adjust. I think what we want is very straightforward and reasonable. (and possibly already exists).
Let's think of a good name. But I think eventually it'll be the only way for us to reconcile this with "incomplete build" problem. |
This is a really elegant solution. I think youtube is enough of a special case that we can keep it untouched for now. Getting this done without a new concept is great. |
Alright, I've updated the code with |
One thing to notice is that I removed the YouTube thumbnails hack and now using |
Can we just leave youtube unchanged? |
Yeah we can leave the old hack in place and not implement the |
Reverted |
@cramforce let me know what do you think about this and if it looks good I can proceed of adding some tests. |
/** | ||
* Allow images inside amp-img to be fit-cover: object. | ||
*/ | ||
amp-img.-amp-object-fit-cover > img { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is this used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah. Inside YouTube - I guess no longer since we reverted back to the hack instead of using amp-img
I can drop this.
Looks great |
.-amp-element > [placeholder] { | ||
display: none; | ||
} | ||
.-amp-element > [placeholder]:last-of-type { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately this doesn't really mean what I thought it meant. This only checks the tag so this wouldn't work as expected unless the placeholders are of the same tag type.
This breaks things, multiple placeholders will still show if they're of different types because the selector will match them all. I am trying to think of a way around this but so far coming empty. Let me know if you have ideas on how to deal with this.
cc/ @cramforce @erwinmombay @dvoytenko - see for more details #2830
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found a way to do this but for the first match using ~ selector
See: http://stackoverflow.com/a/8539107/646979
However, I doubt this can work somehow for last match. So one way to work this out is for us to adapt the first placeholder instead of the last. The problem with this is that in case the double placeholder problem happens, our CSS would choose the dynamic placeholder instead of the user provided one which doesn't really solve the whole problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok after tons of experiments it seems it is impossible to do last-match in CSS as we want here. I came up with a different idea of how to approach this. Still in CSS.
Instead of hiding placeholders we just show all placeholders with trbl=0 as it's currently is. The only difference is that we set a background for the placeholders (e.g. #efefef
), this will force the last placeholder to show at the top and virtually hide all the other placeholders.
The other change that we'd need to do is with togglePlaceholder
which now needs to toggle ALL placeholders instead of just the one. I don't see any problem with this.
I'll update the code to reflect this but if there are any concerns with this please let me know.
* Finds all child elements that satisfies the callback. | ||
* @param {!Element} parent | ||
* @param {function(!Element):boolean} callback | ||
* @return {Array.<Element>} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
!Array<!Element>
I think we should wait for a final review by @dvoytenko |
@@ -148,6 +148,8 @@ i-amp-sizer { | |||
|
|||
.-amp-element > [placeholder] { | |||
display: block; | |||
/** Background is important to hide all other placeholders below it. */ | |||
background-color: #efefef; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this not too big of a change? All existing placeholders will now get the differing background?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can stick with a white background and maybe make this somewhat less specific so it would allow other selectors to override this correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dropped BG.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great!
setStyles(this.placeholderWrapper_, { | ||
'display': '', | ||
}); | ||
this.togglePlaceholder(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has to go into the runtime level. Whoever calls unlayoutCallback
should also toggle placeholder back on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Moved inside Resources.unlayout
@mkhatib Couple more comments, otherwise looks very good. |
Thanks @dvoytenko moved placeholder toggling to resources. PTAL |
LGTM! This is a great improvement. But let's merge tomorrow if you don't mind. I'd like to squeeze in the |
return this.implementation_.unlayoutCallback(); | ||
const isReLayoutNeeded = this.implementation_.unlayoutCallback(); | ||
if (isReLayoutNeeded) { | ||
this.layoutCount_ = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added this before... In resources-impl.js
, never mind.
How do we get into a situation where there are multiple placeholders? |
@jridgewell this might happen for elements that create dynamic placeholders (youtube and instagram as examples), the reason is that the element would start being built by AMP before all of its tree is ready, so AMP would think there's no placeholder for this element because the placeholder has not actually been parsed by the browser yet. <amp-youtube>
<div placeholder></div> <-- if build starts before this was parsed amp-youtube will dynamically create another placeholder and insert it - leaving us with two placeholders.
</amp-youtube> |
Thanks! This may be impossible to test, but which placeholder is last in that case? We use |
@mkhatib @jridgewell - this would be a very rare problem. We should avoid the whole problem altogether. Let's try to fix #3081 by next canary. |
@mkhatib @jridgewell also important to note - this is the problem we already have today, so we are not making it worse - just trying to make it better. |
@jridgewell yes I think the user provided one would be appended later that's why we take the last placeholder to be the element placeholder. I tested this with something like this, though I am not entirely sure if this really emulates the same situation. <element>
<script>element.appendChild(dynamic-placeholder)</script>
<user-placeholder></user-placeholder>
</element> This would create the following DOM: <element>
<dynamic-placeholder>
<user-placeholder>
</element> |
13d2d91
to
1611d76
Compare
Follow up to #2738 this is another approach we're thinking about how to get prerendering to work. This is a discussion PR to discuss the following approach,
This basically does what we kind of do today but instead of using native elements for placeholders the suggestion from @dvoytenko was to use amp-elements (i.e. amp-img in the examples below). This will allow the resources manager to manage loading these placeholders as well.
Few problems with this approach that I ran into:
amp-youtube
hack for falling back to the hqdefault will no longer work unless we expose load promise for theamp-img
or fire load event for it.