royale-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Harbs <harbs.li...@gmail.com>
Subject Re: [royale-asjs] branch develop updated: Fixes #258. But is that a proper fix?
Date Thu, 07 Jun 2018 21:32:47 GMT

> On Jun 7, 2018, at 10:44 PM, Alex Harui <aharui@adobe.com.INVALID> wrote:
> 
> Are you testing with the selector that sets position!=static throughout the DOM?

No. I’m testing with no extra selectors. I dropped that idea. Thanks for pointing out the
problems with it. :-) I don’t think it’s usually necessary. The real problem turns out
to be the use of offsetParent.

> If not, then I think that the "get what you set" rule has to apply and I would think
that code is necessary.  That was also a rule in Flex.  The following was always true:
> 
> Var value:int = 10;
> someWidget.x = value;
> value == someWidget.x; // this was always true.

This is still true. With the current code in the branch, once set, the getter and setter will
always match.

> Otherwise, I think simple animation code might fail:
> 
> Function timerHandler():void
> {
>  someWidget.x += 10;
> }
> 
> The above reads  x and sets it to x+10.

This will work (and I see animations working perfectly in RoyaleStore). The only case it will
not work is if three conditions are fulfilled:

1. The x value started off being undefined and you do someWidget.x += 10;
2.  The offsetParent is not the parent.
3. The element is offset from the offsetParent at some value other than 0.

I have yet to find a case where this is a problem. If there is, then by all means, I’d like
to know, but I’m willing to bet there’s some way of fixing it other than paying for that
code in UIBase.

> It is not PAYG to worry about the performance of an API that is rarely used.  That is
how PAYG works.  You pay for it when you use it.  If you can lower the cost without making
everyone pay for it, great, but the most important principle is that you cannot make everyone
pay for it just-in-case.  Migrating apps may pay more in order to change less code, but AIUI,
the trend in UI design in general is to get away from absolute positioning and use flexbox
and CSSGrid in order to have responsive UIs, so I don't see x,y performance as important.

I did a lot of profiling. Trust me. It’s important. It’s the single-largest performance
bottleneck I’ve found in Royale apps. Sometimes, you can improve it by being smarter about
where you set x and y values, but not always. It effects every use of x=“” and y=“”
used in MXML. The vast majority of apps will have some x and y value somewhere.

In your animation code example, having the offsetParent code in the setter makes the animation
*way* less efficient. There is a an extra forced reflow for every assignment of the new value.

Also, it’s extra code in UIBase “just in case” we care about the offsetParent relative
position. I don’t see how you can claim it’s not a violation of PAYG. It’s code in UIBase
that is just in case. Also, the vast majority of uses of x and y do not need that code. It’s
“just in case”. It also has nasty side effects. Without a clear need for this code, I
don’t know why you are arguing so strongly to keep it.

> I think you are saying there is a bug in the current code, but it somehow involves offsetParent
changing.  Can you explain what causes offsetParent to change?

If/when the parent (or grandparent or great-grandparent, etc.) element position changes from
static to some other value, the offsetParent will change.

> 
> Thanks,
> -Alex
> 
> On 6/7/18, 12:22 PM, "Harbs" <harbs.lists@gmail.com <mailto:harbs.lists@gmail.com>>
wrote:
> 
>> I hope the current implementation tries to mimic Flash/Flex for backward compatibility
reasons. 
> 
>    Here’s the kicker:
> 
>    I have not yet found a *SINGLE* case yet where this attempt to mimic the Flash/Flex
behavior is necessary to *GET THE SAME RESULT*. Both my own app and the examples that I’ve
tested seem to work perfectly without the offsetParent code. The *ONLY* effect I’ve seen
from this code is that it:
> 
>    1. Causes bugs in the layout lifecycle.
>    2. Causes a significant performance hit when writing x and y values.
> 
>    So, to me the question is *WHAT IS THE CASE WHERE THIS CODE IS ACTUALLY NEEDED*? Sure.
I understand theoretically why it’s needed, but I don’t see an *ACTUAL* problem with removing
the code. It seems to me like the theoretical case can be handled with utility functions.
> 
>    I’ll try to do some more testing, but after my initial tests, I’m questioning
whether this code is serving a function anymore. I remember it being needed at some point
in the past, but it could be it’s legacy code which is no longer useful.
> 
>    Harbs
> 
>> On Jun 7, 2018, at 10:13 PM, Alex Harui <aharui@adobe.com.INVALID> wrote:
>> 
>> I'm not sure I'm understanding.
>> 
>> There is no x,y in HTML/JS, so we can make it mean anything we want it to.  I hope
the current implementation tries to mimic Flash/Flex for backward compatibility reasons. 
We could agree to change that if we really want to, but I think backward-compatibility is
useful here.
>> 
>> In Flex/Flash, if you set the x,y to 10,10, then the object is offset by 10 pixels
from the top-left of the parent.  If you read back x,y it will be 10,10.  However, in Royale,
we map x,y to the "left" and "top" styles.  if the parentNode has position=static, then we
need code to compensate for that.
>> 
>> One way is to make sure nobody has position=static.  That doesn't seem PAYG, might
break snippets from the internet, and can be overridden by someone setting position=static
on an element (not sure why anyone would do that).
>> 
>> Another way is, when you set x,y, we set position!=static on the parent.  I think
we tried that and there was some problem, but maybe we should try that again.  That would
be PAYG, IMO.  It is only applied when used.
>> 
>> But again, I want to understand the fundamental use cases.  The one you cited in
RoyaleStore turned out to be an un-needed hack.  What are the real use cases we need to consider?
 How important/prevalent is setting x,y outside of effects, popups, and absolute layout going
to be?   Otherwise, the code can be inefficient because you only pay for it in rare cases,
which is more PAYG then making every node pay for it "just-in-case".
>> 
>> My 2 cents,
>> -Alex
>> 
>> On 6/7/18, 12:00 PM, "Harbs" <harbs.lists@gmail.com <mailto:harbs.lists@gmail.com>
<mailto:harbs.lists@gmail.com <mailto:harbs.lists@gmail.com>>> wrote:
>> 
>>   I don’t think I was clear enough. The original issue that started this thread
is actually caused by the code which sets the y value based on the parentOffset. If the parentOffset
is ignored, the issue goes away and we don’t have to care about layout lifecycles.
>> 
>>   For the few cases where we need to read and set the *actual observed* x and y positions
based on the offsetParent which might be different than the actual parent, we can use utility
functions to get and set these values.
>> 
>>> On Jun 7, 2018, at 9:27 PM, Harbs <harbs.lists@gmail.com <mailto:harbs.lists@gmail.com>>
wrote:
>>> 
>>>> So, if we don't force position!=static throughout the DOM, then you have
to have code that compensates for that difference.
>>> 
>>> I don’t think I agree. Right now we’re modifying the x and y values because
we *might* care about the offsetParent. That’s not PAYG. In fact, the set values will be
*wrong* if the position of the parent is changed after the x and y values of the child are
set.
>>> 
>>> Based on my observations, most apps will not need to set the values based on
the offsetParent, so hard-wiring that code in is not PAYG. This is especially true since setting
x and y currently forces a reflow of HTML. We’re suffering a major performance hit for no
reason.
>>> 
>>> In cases where we care about the parentOffset, we can use observedX and observedY
utility methods which account for offsetParent. That seems much more PAYG to me.
>>> 
>>> Removing the assumptions of reliance on offsetParent seems to eliminate all needs
to care about parent positioning.
>>> 
>>> My $0.02,
>>> Harbs
>>> 
>>>> On Jun 7, 2018, at 8:23 PM, Alex Harui <aharui@adobe.com.INVALID <mailto:aharui@adobe.com.INVALID>
<mailto:aharui@adobe.com.INVALID <mailto:aharui@adobe.com.INVALID>> <mailto:aharui@adobe.com.INVALID
<mailto:aharui@adobe.com.INVALID><mailto:aharui@adobe.com.INVALID <mailto:aharui@adobe.com.INVALID>>>>
wrote:
>>>> 
>>>> IIRC, the parentNode is always the parent of the child if you examine the
DOM.  offsetParent is the parent or grandparent, etc, that has position != static, and left/top/right/bottom
styles are always relative to offsetParent.  So, if we don't force position!=static throughout
the DOM, then you have to have code that compensates for that difference.
>>>> 
>>>> IMO, the key issue is whether it is "ok" to force position!=static throughout
the DOM.  Can someone look at other JS frameworks?  I'll bet most of them use border-box like
we do.  If the major JS frameworks have opted for position!=static, then it might be the right
thing for us to do as well.  IMO, we would like to make it easy for snippets found on the
internet to work in Royale and they may not all presume position!-static.
>>>> 
>>>> Also, IMO, our Containers should not presume position!=static.  Containers
accept assignable Layouts and the Layouts can set position!=static on the children and be
appropriately named (VerticalLayoutWithXYSupport).  That's PAYG to me.  Remember that TLCs
should have very little assumptions as illustrated in the ExplodedComponent example.  The
beads can make assumptions and be appropriately named and documented.
>>>> 
>>>> My 2 cents,
>>>> -Alex
>>>> 
>>>> On 6/7/18, 6:15 AM, "Harbs" <harbs.lists@gmail.com <mailto:harbs.lists@gmail.com>
<mailto:harbs.lists@gmail.com <mailto:harbs.lists@gmail.com>> <mailto:harbs.lists@gmail.com
<mailto:harbs.lists@gmail.com> <mailto:harbs.lists@gmail.com <mailto:harbs.lists@gmail.com>>>>
wrote:
>>>> 
>>>>  I created a “simplify-position” feature branch which does away with
the offsetParent logic in UIBase. It does not change anything regarding position: static.
>>>> 
>>>>  I have tested with my own app and a number of the examples. I haven’t
found any problems yet.
>>>> 
>>>>  Input welcome…
>>>> 
>>>>  Harbs
>>>> 
>>>>> On Jun 7, 2018, at 12:20 PM, Harbs <harbs.lists@gmail.com <mailto:harbs.lists@gmail.com>
<mailto:harbs.lists@gmail.com <mailto:harbs.lists@gmail.com>> <mailto:harbs.lists@gmail.com
<mailto:harbs.lists@gmail.com> <mailto:harbs.lists@gmail.com <mailto:harbs.lists@gmail.com>>>>
wrote:
>>>>> 
>>>>>> So, IMO, it would be nice to do a similar investigation of controlsPallette.
>>>>> 
>>>>> You are right. Removing the y value has no effect.
>>>>> 
>>>>> I am wondering that maybe it makes sense to apply relative to the Container
CSS selector and possibly a few others.
>>>>> 
>>>>> I’m trying to understand the specific cases where:
>>>>>              if (positioner.parentNode != positioner.offsetParent)
>>>>> 
>>>>> Is required in setX, get x and setY, get y in UIBase. I would *really*
like to get rid of that code, and I’m, wondering what doing so would cause.
>>>>> 
>>>>>> On Jun 7, 2018, at 12:36 AM, Alex Harui <aharui@adobe.com.INVALID
<mailto:aharui@adobe.com.INVALID> <mailto:aharui@adobe.com.INVALID <mailto:aharui@adobe.com.INVALID>>
<mailto:aharui@adobe.com.INVALID <mailto:aharui@adobe.com.INVALID><mailto:aharui@adobe.com.INVALID
<mailto:aharui@adobe.com.INVALID>>> <mailto:aharui@adobe.com.INVALID <mailto:aharui@adobe.com.INVALID>
<mailto:aharui@adobe.com.INVALID <mailto:aharui@adobe.com.INVALID>><mailto:aharui@adobe.com.INVALID
<mailto:aharui@adobe.com.INVALID><mailto:aharui@adobe.com.INVALID <mailto:aharui@adobe.com.INVALID>>>>>
wrote:
>>>>>> 
>>>>>> In the case of the controlsPallette, how did it get its size?  I
could certainly understand that if you didn't have position!=static, that setting top on the
dockAndOuterContainer would have no effect, but you shouldn't have had to set y or top in
the first place.  IIRC, you couldn't use x,y in Flex layouts like VerticalLayout/HorizontalLayout
so migrating code shouldn't be using it.  It is fine to create other layouts that support
x,y as exceptions.
>>>>>> 
>>>>>> In general, for a framework, we want to make sure we understand and
fix the fundamental problem before we address any hacks/exceptions.  IMO, the fundamental
problem in the scenarios you've provided so far is that the layout did not do what was expected
so someone tried using x,y to fix it.  First we need that layout do what is expected, then
worry about how folks might resolve other issues, if any.
>>>>>> 
>>>>>> In ProductsView in RoyaleStore, the grip is an image loaded later,
so there might have been an issue there, especially on the SWF side, but I would expect the
browser to automatically re-layout once the grip image loaded.  I dug through Git history
and found that I was the one who hacked in the x,y.  It could be that early on, the layout
did not use FlexBox so we had a similar problem of responding to the grip image loading late.
 But we should remove the x,y and see if there is still a problem and ponder the right fix
for that.  ProductsView should not need to be setting x,y.
>>>>>> 
>>>>>> So, IMO, it would be nice to do a similar investigation of controlsPallette.
 IMO, if you examine that div, it's offsetHeight should be 40 and if it is then you shouldn't
need to set style.top=40 on docAndOuterContainer which means that it shouldn't matter what
style.position is.
>>>>>> 
>>>>>> My 2 cents,
>>>>>> -Alex
>>>>>> 
>>>>>> On 6/6/18, 2:12 PM, "Harbs" <harbs.lists@gmail.com <mailto:harbs.lists@gmail.com>
<mailto:harbs.lists@gmail.com <mailto:harbs.lists@gmail.com>> <mailto:harbs.lists@gmail.com
<mailto:harbs.lists@gmail.com> <mailto:harbs.lists@gmail.com <mailto:harbs.lists@gmail.com>>>
<mailto:harbs.lists@gmail.com <mailto:harbs.lists@gmail.com> <mailto:harbs.lists@gmail.com
<mailto:harbs.lists@gmail.com>> <mailto:harbs.lists@gmail.com <mailto:harbs.lists@gmail.com>
<mailto:harbs.lists@gmail.com <mailto:harbs.lists@gmail.com>>>>> wrote:
>>>>>> 
>>>>>> 
>>>>>>> On Jun 6, 2018, at 11:05 PM, Harbs <harbs.lists@gmail.com
<mailto:harbs.lists@gmail.com> <mailto:harbs.lists@gmail.com <mailto:harbs.lists@gmail.com>>
<mailto:harbs.lists@gmail.com <mailto:harbs.lists@gmail.com><mailto:harbs.lists@gmail.com
<mailto:harbs.lists@gmail.com>>> <mailto:harbs.lists@gmail.com <mailto:harbs.lists@gmail.com>
<mailto:harbs.lists@gmail.com <mailto:harbs.lists@gmail.com>><mailto:harbs.lists@gmail.com
<mailto:harbs.lists@gmail.com><mailto:harbs.lists@gmail.com <mailto:harbs.lists@gmail.com>>>>>
wrote:
>>>>>>> 
>>>>>>> 		<js:Label x="20" y="20"
>>>>>>> 				  text="{locStr.UPLOAD_YOUR_IMAGE}"/>
>>>>>>> 
>>>>>> 
>>>>>> It actually, looks like the x and y values no longer have an effect
on this particular component, but there was clearly a reason they were needed to be specified
at some point…
>>>>>> 
>>>>>> Another one. I have an image which needs to stick to the bottom right
of the app. To do that I needed to following:
>>>>>> 
>>>>>>   top: calc(100% - 21px);
>>>>>>   left: calc(100% - 187px);
>>>>>>   position: fixed;
>>>>>> 
>>>>>> With a default of position: relative, I’m able to do this:
>>>>>> 
>>>>>>     top: -21px;
>>>>>>     float: right;
>>>>>>     right: 10px;
>>>>>> 
>>>>>> This being said, it actually looks like I’m wrong about the way
to set the defaults being .Application *{}. This actually has a *higher* specificity than
.foo{}.[1]
>>>>>> 
>>>>>> I think the only way to guarantee that it’ll have a lower specificity
than other selectors is to use:
>>>>>> 
>>>>>> *{
>>>>>> position: relative;
>>>>>> }
>>>>>> 
>>>>>> I’m less happy about this option than ."Application *” because
it’ll effect elements outside the Royale app if it’s not in an iframe.
>>>>>> 
>>>>>> Harbs
>>>>>> 
>>>>>> [1]https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0>
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0>>
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0>
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0>>>
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0>
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0>>
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0>
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0>>>>
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0>
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0>>
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0>
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0>>>
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0>
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0>>
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0>
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0
<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.smashingmagazine.com%2F2007%2F07%2Fcss-specificity-things-you-should-know%2F&data=02%7C01%7Caharui%40adobe.com%7C36c2eb99bf2e4b45c44d08d5cbf2422f%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636639163710627765&sdata=1YPJLfmzcaeFlh%2Bu2FTmbTHgvIvS6n%2BhVQiZhiucJqs%3D&reserved=0>>>>>


Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message