These are chat archives for japgolly/scalacss

2nd
Apr 2015
Matt Hughes
@matthughes
Apr 02 2015 01:04
I didn't realize the styleS difference. Good to know. But in #25 I feel like I'm missing something. Why would the name of a "mixed in" style affect the outer style? What would happen if I mixed in three styles? I actually was under the impression that mixing in a style just meant that the call site would accumulate classnames.
```val foo = style("foo")(..."); val bar = style("bar")(..., foo);
val foo = style("foo")(..."); val bar = style("bar")(..., foo); div(bar) == div(className := "foo bar")
Li Haoyi
@lihaoyi
Apr 02 2015 01:12
@matthughes I considered that approach for Scalatags' CSS and ultimately went with the flatten-it-out approach
I have no good reason for it
=P
other than that it makes debugging
much easier
than seeing a chain of 20 mixed in classes
in the generated HTML
Matt Hughes
@matthughes
Apr 02 2015 01:13
There is also the approach of inlining everything into a style attribute. I do wonder if that would improve rendering performance.
Won't work for selectors, but plain classes could be inlined.
Li Haoyi
@lihaoyi
Apr 02 2015 01:13
one interesting thing is that
plain classes are selectors too
=D
I get around this via cls.splice for inlining and cls for treating as selector
Matt Hughes
@matthughes
Apr 02 2015 01:14
And presumably flat classes could be faster for the CSS engine. Rather than having to do multiple levels of lookup. Pure conjecture on my part and probably not a slow part of most websites anyway.
Li Haoyi
@lihaoyi
Apr 02 2015 01:14
yeah
it doesn't even matter for file-size
if you gzip things
Matt Hughes
@matthughes
Apr 02 2015 01:15
Or if you generate it on the client :)
That's how I'm using it right now. AFAICT I would, the style-related JS would get generated even if I generated it on the server anyway.
Li Haoyi
@lihaoyi
Apr 02 2015 01:16
that's not strictly true
you can have a StubStylesheet that's shared between client and server
and a FullStylesheet extends StubStylesheet that only lives on the server
so you can be guaranteed they'll be in sync but your client only gets the class-names and that's all
Matt Hughes
@matthughes
Apr 02 2015 01:17
this is a scalatags feature I'm guessing?
Li Haoyi
@lihaoyi
Apr 02 2015 01:17
not really a scalatags feature
it's just inheritance
=P
but yeah it works in Scalatags
Matt Hughes
@matthughes
Apr 02 2015 01:27
@japgolly Would you expect this warning?

``` val styleA = style(
display.block
)

val styleB = style(
display.block,
styleA
)

// [CSS WARNING] .scalacss-0002 -- display overridden by display."
```

bah my formatting skillz are bad tonight
It's issuing a warning, but the display values are the same. I would think it would only warn if mixed in values conflict.
David Barri
@japgolly
Apr 02 2015 03:39
@matthughes Basically it's an over-sight. What you're doing should work as you'd expect. I'll fix it for 0.2.0 so it does :)
@matthughes Warnings are just like debugging info cos especially in large apps it's very frikkn hard to merge styles and know what causes problems and see what you're breaking.
(At least that's been my unpleasant experience.)
At the moment this only checks, when styles are merged, if they both modify the same attributes (directly or indirectly).
I haven't put any logic in to actually compare the values. It would make sense. Would you mind raising a ticket for it?
Otto Chrons
@ochrons
Apr 02 2015 06:38
@japgolly what I meant is to define, for example, a style for tr tags under a table with specific CSS class. Is there any other way than unsafeChild if I don't want to explicitly set a style to the tr tags
so like table.myStyle tr { font-size: small } kinda definition
David Barri
@japgolly
Apr 02 2015 06:42
I don't follow.
styleC is the safe way of composite styles.
There's unsafeChildren and unsafeRoot.
You could use unsafeRoot("table.myStyle tr") for your example?
Otto Chrons
@ochrons
Apr 02 2015 06:43
yea, but I don't want to use unsafe
David Barri
@japgolly
Apr 02 2015 06:43
I don't understand
Otto Chrons
@ochrons
Apr 02 2015 06:43
with styleC can you do the same, apply a style to child tr tags without explicitly setting the style on those in the code?
David Barri
@japgolly
Apr 02 2015 06:43
styleC then?
Otto Chrons
@ochrons
Apr 02 2015 06:44
<.table(myStyle, <.tr("blaa"))
David Barri
@japgolly
Apr 02 2015 06:44

without explicitly setting the style on those in the code

↑ well that would be unsafe :)

oh wait
yeah
oh wait
unsafe is to prevent against two things:
  1. Needed style not being applied to children.
  2. Decouple usage order from upstream declaration order. (as all the types are the same)
Also: 3. Compiler-aware link between styles and usage.
If you don't connect the tr style to the tr manually then you'll never know which styles are being used and which you can delete
Thus you may as well just use an external CSS
You the benefits of inline styling like refactoring, tracability and dead-code(style) detection
Which is why you can still achieve your goal, but with the unsafe disclaimer.
Make sense?
Otto Chrons
@ochrons
Apr 02 2015 06:50
sure I could do it the styleC way, but in the case of table the structure is well defined by HTML (unlike the example you provide for styleC) so I don't really see how it would be so unsafe
David Barri
@japgolly
Apr 02 2015 06:51
The style doesn't know (and scalac doesn't have evidence) that the style is only for table elements.
Everything is clear and easy when you write styles but what about later if some other developer changes one of the style targets to use a flex box or something.
It doesn't have to be verbose or intimidating, this is a snippet I wrote the other day for auto-completion items:
val reqAutoComplete = styleC {
  val r = styleS(fontWeight.bold)
  val d = styleS(color("#444"), fontStyle.italic, overflow.hidden, maxWidth(36 ex))
  r.named('req) :*: d.named('desc)
}

def li(v: LookupV): ReactElement =
  *.reqAutoComplete('req)(r => _('desc)(d =>
    <.div(
      <.div(r, v.label),
      <.div(d, v.desc))
  ))
David Barri
@japgolly
Apr 02 2015 06:56
It feels a little odd to me too cos it's so different than the norm, but after careful thought it makes a lot of sense. I trust my reasoning more than what I'm used to. :grinning:
Otto Chrons
@ochrons
Apr 02 2015 06:57
it feels like an overprotective mother :D
but breakfast time
David Barri
@japgolly
Apr 02 2015 06:58
Haha, I wonder if this is how programmers used to dynamic-typing feel when they first start using static-typing. I imagine it's similar.
Trust in reasoning and long-term benefits! And breakfast.
By the way, if you try styleC there's a temporary issue - you'll have to add an import to the call-site. I'll fix this in 0.2.0. #24
Otto Chrons
@ochrons
Apr 02 2015 07:13
how do you refactor the symbol names in styleC, do IDEs support that?
also is there any "code completion" for them, or do you need to look it up from the style source everytime? :)
David Barri
@japgolly
Apr 02 2015 07:15
No & no. You have to look every time :( and the refactoring story is that scalac catches you when you don't propagate changes :D manually :( .
Otto Chrons
@ochrons
Apr 02 2015 07:16
I always was a bit suspicious about using symbols :)
David Barri
@japgolly
Apr 02 2015 07:16
Yeah it's totally out-of-the-box thinking
You know there's a different trade-off:
We can get better IDE support (1 - refactor the constituent names, 2 - autocomplete the constituent names) if we drop one safety feature:
  1. Needed style not being applied to children.
Because then we can just use classes.
It's all about balancing trade-offs. I keep forgetting (too much on my mind this month) but adding the above as another option available to users would probably be a good idea right?
I think most ppl would be much more receptive to it.
Otto Chrons
@ochrons
Apr 02 2015 07:20
yeah, would make the use of it less complex
David Barri
@japgolly
Apr 02 2015 07:21
Personally, I don't really think it's complex as is, just... alien.
:alien:
Otto Chrons
@ochrons
Apr 02 2015 07:27
if you take a look at https://github.com/twbs/bootstrap/blob/master/less/tables.less and especially the different .table-XXX styles, how would those be implemented efficiently in ScalaCSS? Especially if you want to apply multiple styles to the table
David Barri
@japgolly
Apr 02 2015 07:29
I'll take a look later, I'm (supposed to be) writing tests now :)
Also, let me know how you think they could be written :+1:
Otto Chrons
@ochrons
Apr 02 2015 07:30
not with styleC, that's for sure, because you have multiple overlapping styles for different components like tr :)
but I think table is a bit special case, since it has such a well defined structure in HTML
you don't run into this with other HTML tags
David Barri
@japgolly
Apr 02 2015 07:31
Keep mind though that this lib isn't for creating generic css libs like bootstrap.
The requirements there are going to differ.
That excerpt "multiple overlapping styles" makes me shiver and feel scared.
Otto Chrons
@ochrons
Apr 02 2015 07:33
I meant using "table-striped" and "table-bordered" for the same table, which results in overlapping style definitions for all the underlying tags
David Barri
@japgolly
Apr 02 2015 07:33
Ah that feels more relatable
Hmm well composability of composite styles is probably the hardest problem to solve.
Otto Chrons
@ochrons
Apr 02 2015 07:35
so composing those kinds of "high level" styles that also define styles for children
but as I said, table is about the only place where that is really needed
maybe some list structures too, to a limited amount
David Barri
@japgolly
Apr 02 2015 07:37
In a type-safe world, two arbitrary composite styles would need to be manually stitched together. A+B would need different logic than A+C. I think in a type-safe world you would do it manually (which I think you can do now). Some helpers could be introduced to help the process.
In an untyped world you could just smash shit together by name :P
I'm not sure how well that would work out though.
Maybe there needs to be a process of bringing two composites in sync and then the merging could be automatic.
So A+B you either turn A into a B' or B into an A' and then combine two of the same type (?)
I don't know yet, it'd be great if someone told me.
Otto Chrons
@ochrons
Apr 02 2015 07:40
I'm no CSS expert, so cannot really say what would be the best course of action
David Barri
@japgolly
Apr 02 2015 07:40
Everything I can think of requires us to abandon solutions to problems we set out to solve with this lib in the first place :(
Otto Chrons
@ochrons
Apr 02 2015 07:40
just looking at some specific use cases and thinking how they could be implemented
David Barri
@japgolly
Apr 02 2015 07:41
Yeah me either man, I'm realising that my JS/CSS knowledge is outdated (about 8 years old)
You know, problem we're discussing could be solved nicely with stylec
It would just get a bit boilerplatey
But it would be correct and maintain the long-term fbenefits
I think it'd be too annoying that noone would do it though.
Theory: :+1: Practice: :goberserk:
Otto Chrons
@ochrons
Apr 02 2015 07:44
yup
so, if I really want to do that kind of .myStyle > thead style definition now, it would involve using unsafeChild?
val myStyle = style(blaablaa... , unsafeChild("> thead")( blaablaa) )
David Barri
@japgolly
Apr 02 2015 07:50
Hold on
Here's an example using styleC
  val blah1 = styleC {
    val a = styleS(/*...*/)
    val b = styleS(/*...*/)
    a.named('table) :*: b.named('tr)
  }

  val blah2 = styleC {
    val a = styleS(/*...*/)
    val b = styleS(/*...*/)
    a.named('outer) :*: b.named('tableRow)
  }
Two different composite styles...
  val blah3 = styleC {
    blah1('table)(a1 => _('tr)(b1 =>
    blah2('outer)(a2 => _('tableRow)(b2 => {
      val a = styleS(a1, a2)
      val b = styleS(b1, b2)
      a.named('outside) :*: b.named('inside)
    }))))
  }
Merging them ↑
I also just realised I could easily make them compose with just + when the names line up....
For example blah1 + blah1
As to your question, yes, I believe you could use unsafeChild instead, just like your example.
Otto Chrons
@ochrons
Apr 02 2015 07:56
thought so
David Barri
@japgolly
Apr 02 2015 11:36
@ochrons I know what to do.
Stylesheet.InlineLoose and Stylesheet.InlineStrict
In strict, unsafe things are marked unsafe. In loose it's more like SCSS/LESS or the standalone stylesheets.
In loose instead of unsafeChild("tr") you can just do "tr" { ... } or something.
Otto Chrons
@ochrons
Apr 02 2015 11:41
or use actual elements (like in Scalatags CSS) to define them, to be more safe :)
David Barri
@japgolly
Apr 02 2015 11:44
hmmm yeah I could do that
so tr { ... }
& > tr { ... }
Otto Chrons
@ochrons
Apr 02 2015 11:45
looking good to me :)
David Barri
@japgolly
Apr 02 2015 11:45
Hmm ok
Actually I think: &.tr { ... } instead of tr { ... }

Do you (or anyone else) think it'd be a problem if I changed:

val blah = style(
  fontWeight.bold,
  &.hover(color.red)
)

to

val blah = style(& =>
  fontWeight.bold,
  &.hover(color.red)
)

?

In top exaxmple, if & is used outside of a style(...) then I can't control it. I just gets ignored.
Otto Chrons
@ochrons
Apr 02 2015 12:08
well, it's an additional complication, so I wonder if the benefits outweigh the disadvantages
Otto Chrons
@ochrons
Apr 02 2015 19:17
SPA tutorial is now Powered by ScalaCSS :D (http://ochrons.github.io/scalajs-spa-tutorial/css-in-scala.html)
David Barri
@japgolly
Apr 02 2015 20:59
Woah that's awesome man!
Hey how did you find using Gitbook?
Otto Chrons
@ochrons
Apr 02 2015 21:01
simple enough
all I had to change was some relative links to be absolute, otherwise it was trivial copy-pasting
unfortunately I don't really use that much CSS in the tutorial, so it's basically just about how to deal with external CSS :)
David Barri
@japgolly
Apr 02 2015 21:19
Oh btw @ochrons I'm going to use your idea
(Well, with some differences - fine, most of your idea :P )
I'm going to have an object where you can give
GlobalSomething.giveMeInstance[BootstrapStyles]
Based on the register sink idea.
At the beginning of your app somewhere, if you choose this approach, you can register stuff globally like the sink idea.
GlobalSomething register BootstrapStyles
GlobalSomething register MyAppStyles
then later
GlobalSomething.giveme[BootstrapStyles]
David Barri
@japgolly
Apr 02 2015 21:25
It's objects, don't have to pass around styles classes if you don't want to. (But people who want to still can.)
Sound good? Also @chandu0101 , would this work well for you too?
David Barri
@japgolly
Apr 02 2015 21:36
I'll also make it so you can just have object stylesheets and just call addToDocument() on multiple independent things.
I want to provide tools here. I want people to be able to develop the way they think is best :)
David Barri
@japgolly
Apr 02 2015 23:02
Some changes. In dev-mode, stylesheets will now be prefixed by their class/object name, so .MyStyles-0001 instead of .scalacss-0001
DefaultsTest.scala#L21-L74
In prod-mode, when different stylesheets are registered, they get different prefixes. DefaultsTest.scala#L80-L109
/cc @chandu0101
You will be able to call addToDocument() on multiple SS's without conflict.
Chandra Sekhar Kode
@chandu0101
Apr 02 2015 23:09
nice :) , I was busy with some other things these days, I'll try again soon.
David Barri
@japgolly
Apr 02 2015 23:14
no worries mate, i should have 0.2.0 released in < 1 week
Not all feedback will be accomodated but the biggest things should