CSS for colour changes in ui-template / HSLA colour picker

This dashboard plays with a template including:

  • A background texture (ruled paper) and text that fits between the lines.
  • Google handwriting fonts.
  • Sizes defined as rem and lh.
  • CSS transform.

Since many of these things are new to me, there are no doubt many errors and better ways to achieve the effects

It does not scale well to a phone screen in portrait mode.
For more info see the flow description.

[{"id":"fbb0a5cd0ab55ab1","type":"tab","label":"Macbeth","disabled":false,"info":"This dashboard plays with a template including:\r\n - A background texture (ruled paper) and text that fits between the lines.\r\n - Google handwriting fonts.\r\n - Sizes defined as rem and lh.\r\n - CSS transform.\r\n\r\nIt does not scale well to a phone screen in portrait mode.\r\n\r\nThe notepaper styling is based on https://codepen.io/kevinpowell/pen/dyavyPg\r\n\r\n---\r\n\r\nDynamically styled elements on this dashboard:\r\n 1. The text colour on the notepaper.\r\n 2. The angle of rotation of the notepaper.\r\n 3. The colour of the Post-It note.\r\n\r\n Every message passed to the template must include all styling properties else eg the rotation sets to 0.\r\n So there are initial values for all properties. \r\n I don't know any way to ignore eg missing msg.payload.rotate.\r\n\r\nThe notepaper is declared thus\r\n    <div class=\"notepaper\"\r\n        :class=\"msg.payload.textcolor\"\r\n        :style=\"msg.payload.rotate\">\r\nIt has:\r\n1. A static class\"notepaper\". Styling for this class gived the lined paper effect.\r\n\r\n2. A dynamic class name passed in via msg.payload.textcolor (\"red\", \"green\" or \"skybluepink\")\r\n    Example msg.payload.textcolor = \"green\"\r\n    CSS for these classes :\r\n        .red .text p {\r\n            color: darkred;\r\n        }\r\n        .green .text p {\r\n            color: darkgreen;\r\n        }\r\n    No valid class for skybluepink - it just reverts to default black\r\n\r\n3. A style applied to the div passed in via msg.payload.rotate\r\n   (it's not possible to define a class for every possible rotation value)\r\n    Example msg.payload.rotate = \"transform: rotate(2deg)\"\r\n    This is a fudge because you cannot use text interpolation in the <style> section of the code\r\n    ie this is not valid\r\n        .notepaper {\r\n            transform : \"msg.payload.rotate\";\r\n        }\r\n    Hopefully a future release will permit text interpolation here.\r\n\r\nNote that you could pass msg.payload.rotate = 5 and assemble the definition in the declaration of the div\r\n    Example <div class=\"swatch\" :style=\"{'background-color': msg.payload}\">\r\nHowever I can't work out how to do it :style=\"('transform': 'rotate(' msg.payload 'deg)'\" breaks the browser tab.\r\nI find it easier if I pass the entire style as a string \"transform: rotate(2deg)\".\r\n\r\n---\r\n\r\nThe Post-It note is declared thus\r\n    <div class=\"postitinner\"\r\n    :style=\"{'background-color': msg.payload.postItColor}\">\r\n\r\nExample msg.payload.postItColor = hsla(359, 100%, 80%, 88%)\r\nIt uses HSLA color space but you could just as well have msg.payload.postItColor = \"#FFD700\"\r\n\r\n---\r\n\r\nCSS declared in the <style> section of a template gets applied to all templates on the page.\r\nProbably better to have a dedicated CSS template.\r\nhttps://vuejs.org/guide/essentials/class-and-style.html#binding-html-classes has more complex examples\r\nbut many of them need the <script> section of the template.\r\n\r\n---\r\n\r\n\r\n","env":[]},{"id":"f3c5c6ce9c5fae46","type":"group","z":"fbb0a5cd0ab55ab1","name":"Variable colour as HSLA ","style":{"label":true},"nodes":["8ebbc4f5e85f3a71","8b91e038224d721c","6608e217685b213a","d312461d30f31272","52b62baf3f28e261","44b40de04680b4a9","61f311a8b5b35e7e","cec6f8cdaf344fb6","5d6a97a1565a4bd3","880bdbee13d8a110"],"x":14,"y":19,"w":552,"h":202},{"id":"b8dda7966a82b2a9","type":"group","z":"fbb0a5cd0ab55ab1","name":"Rotation control","style":{"label":true},"nodes":["511c22b45b9c7df4","dab9fd870355b3bc","9f79038bb989dbbc"],"x":14,"y":239,"w":452,"h":82},{"id":"475c4ee4351613f0","type":"group","z":"fbb0a5cd0ab55ab1","name":"Notebook text colour","style":{"label":true},"nodes":["45f4f13e4f7cde29","41b5f3d452d19958","6bf3ec324642befb","a2eb1124d51f64c6"],"x":14,"y":339,"w":352,"h":162},{"id":"8f9260ec76e79af3","type":"ui-template","z":"fbb0a5cd0ab55ab1","group":"d2f6d8d511f82b37","page":"","ui":"","name":"","order":1,"width":"0","height":"0","head":"","format":"<template>\n        <link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css?family=Charmonman\">\n        <link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css?family=Water Brush\">\n    <div class=\"notepaper\"  \n        :class=\"msg.payload.textcolor\"\n        :style=\"msg.payload.rotate\">\n        <div class=\"postit\">\n            <div class=\"postitinner\" :style=\"{'background-color': msg.payload.postItColor}\">\n                <h2>Macbeth</h2>\n                <p>Something Wicked</p>\n                <p><br/></p>\n                <p>The Globe</p>\n                <p>September 24</p>        \n            </div>\n        </div>\n        <div class=\"header\"><h3>Act 4, Scene 1</h3></div>\n        <div class=\"player\"><p>FIRST WITCH:</p></div> \n        <div class=\"text\"><p>Thrice the brinded cat hath mew'd.</p></div>\n        <div class=\"player\"><p>SECOND WITCH:</p></div>\n        <div class=\"text\"><p>Thrice and once the hedge-pig whined.</p></div>\n        <div class=\"player\"><p>THIRD WITCH:</p></div>\n        <div class=\"text\"><p>Harpier cries, “’Tis time, ’tis time.”</p></div><br/>\n        <div class=\"player\"><p>FIRST WITCH:</p></div>\n        <div class=\"text\"><p>Round about the cauldron go:<br/>\n            In the poison'd entrails throw.<br/>\n            Toad, that under cold stone<br/>\n            Days and nights has thirty-one<br/>\n            Swelter'd venom sleeping got,<br/>\n            Boil thou first i’ the charmed pot.</p></div>\n        <div class=\"player\"><p>ALL: </p></div>\n        <div class=\"text\"><p>Double, double toil and trouble;<br />\n            Fire burn, and cauldron bubble.</p>\n        </div>\n        <div class=\"player\"><p>SECOND WITCH: </p></div>\n        <div class=\"text\">\n            <p>Fillet of a fenny snake<br/>\n            In the cauldron boil and bake.<br/>\n            Eye of newt and toe of frog,<br/>\n            Wool of bat and tongue of dog,<br/>\n            Adder’s fork and blindworm’s sting,<br/>\n            Lizard’s leg and howlet’s wing,<br/>\n            For a charm of powerful trouble,<br/>\n            Like a hell-broth boil and bubble.</p>\n        </div>\n        <div class=\"player\"><p>ALL: </p></div>\n        <div class=\"text\"><p>Double, double toil and trouble;<br/>\n            Fire burn, and cauldron bubble.</p>\n        </div>\n    </div>\n    \n</template>\n\n\n<style>\n    :root {\n        --main-line-color: hsl(234, 62%, 86%);\n        --side-line-color: hsl(350, 100%, 91%);\n        --paper-colxor: hsl(0, 15%, 95%);\n        --paper-color: hsl(42, 30%, 95%);\n        --ink-color: hsl(0, 0%, 12%);\n        --line-thickness: 2px;\n        --top-space: 1lh;\n    }\n    .postit {\n        position: absolute;\n        min-height: 20rem;\n        padding-top: 2rem;\n    }\n    .postitinner {\n        position: relative;\n        min-width: 20rem;\n        min-height: 20rem;\n        transform: rotate(-5deg) translate(25%, 25%);\n        box-shadow: rgba(0, 0, 0, 0.3) 0px 19px 38px, rgba(0, 0, 0, 0.22) 0px 15px 12px;\n        border-bottom-right-radius: 60px 5px;\n        text-align: center;\n        padding-top: 2rem;\n    }\n    .postitinner h2 {\n        font-family: \"water brush\", serif;\n        font-size: 3.5rem;\n    }\n    .postitinner p {\n        font-family: \"charmonman\", sans-serif;\n        font-size: 2rem;\n    }\n\n    .notepaper {\n        position: relative;\n        font-family: verdana, sans-serif;\n        font-size: 1.1rem;\n        background: var(--paper-color);\n        margin: 1rem;\n        padding: calc(var(--top-space) - 0.2lh) 3rem 5rem 5rem;\n        color: var(--ink-color);\n        background-image:\n            /* the red line */ linear-gradient(90deg, transparent, transparent 4rem,\n            var(--side-line-color) 4rem, var(--side-line-color) 4.25rem, transparent 4.25rem ),\n            /* The top space */ linear-gradient(var(--paper-color), var(--paper-color) var(--top-space), transparent var(--top-space)),\n            /* the blue lines */\n            repeating-linear-gradient(transparent, transparent calc(1lh - var(--line-thickness)),\n            var(--main-line-color) calc(1lh - var(--line-thickness)),\n            var(--main-line-color) 1lh, transparent 1lh);\n        box-shadow: 0 0 0.5rem rgb(0 0 0 / 0.25);\n    }\n    .notepaper .player {\n        float: left;\n        width: 27%;\n    }\n    .notepaper .text {\n        float: left;\n        width: 73%;\n    }\n    .notepaper .text p {\n        padding-bottom: 1lh;\n    }\n    .red .text p {\n        color: darkred;\n    }\n    .green .text p {\n        color: darkgreen;\n    }\n</style>\n","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":800,"y":280,"wires":[[]]},{"id":"511c22b45b9c7df4","type":"ui-slider","z":"fbb0a5cd0ab55ab1","g":"b8dda7966a82b2a9","group":"74f264f9df3eda4f","name":"","label":"Rotation","tooltip":"","order":1,"width":"0","height":"0","passthru":true,"outs":"all","topic":"topic","topicType":"msg","thumbLabel":"true","showTicks":"false","min":"-10","max":10,"step":1,"className":"","iconPrepend":"","iconAppend":"","color":"","colorTrack":"","colorThumb":"","x":240,"y":280,"wires":[["dab9fd870355b3bc"]]},{"id":"d47da04968907a09","type":"comment","z":"fbb0a5cd0ab55ab1","name":"Explanatory Notes in Flow Description","info":"","x":730,"y":40,"wires":[]},{"id":"dab9fd870355b3bc","type":"function","z":"fbb0a5cd0ab55ab1","g":"b8dda7966a82b2a9","name":"Set rotate","func":"msg.payload = \"transform: rotate(\" + msg.payload +\"deg)\"\nmsg.topic = \"rotate\"\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":380,"y":280,"wires":[["aff2b2585a969558"]]},{"id":"8ebbc4f5e85f3a71","type":"inject","z":"fbb0a5cd0ab55ab1","g":"f3c5c6ce9c5fae46","name":"Init","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"Hue","payload":"359","payloadType":"str","x":110,"y":60,"wires":[["8b91e038224d721c"]]},{"id":"8b91e038224d721c","type":"ui-slider","z":"fbb0a5cd0ab55ab1","g":"f3c5c6ce9c5fae46","group":"74f264f9df3eda4f","name":"Hue","label":"Hue","tooltip":"","order":5,"width":"0","height":"0","passthru":true,"outs":"all","topic":"hue","topicType":"str","thumbLabel":"true","showTicks":"false","min":0,"max":"359","step":1,"className":"","iconPrepend":"","iconAppend":"","color":"","colorTrack":"","colorThumb":"","x":270,"y":60,"wires":[["61f311a8b5b35e7e"]]},{"id":"6608e217685b213a","type":"function","z":"fbb0a5cd0ab55ab1","g":"f3c5c6ce9c5fae46","name":"format as HSLA","func":"msg.payload = \"hsla(\" + msg.payload.hue + \", \" + msg.payload.saturation + \"%, \" + msg.payload.lightness + \"%, \" + msg.payload.alpha + \"%)\"\nmsg.topic = \"postItColor\"\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":460,"y":180,"wires":[["aff2b2585a969558"]]},{"id":"d312461d30f31272","type":"ui-slider","z":"fbb0a5cd0ab55ab1","g":"f3c5c6ce9c5fae46","group":"74f264f9df3eda4f","name":"Saturation","label":"Saturation","tooltip":"","order":6,"width":"0","height":"0","passthru":true,"outs":"all","topic":"saturation","topicType":"str","thumbLabel":"true","showTicks":"false","min":0,"max":"100","step":1,"className":"","iconPrepend":"","iconAppend":"","color":"","colorTrack":"","colorThumb":"","x":250,"y":100,"wires":[["61f311a8b5b35e7e"]]},{"id":"52b62baf3f28e261","type":"ui-slider","z":"fbb0a5cd0ab55ab1","g":"f3c5c6ce9c5fae46","group":"74f264f9df3eda4f","name":"Lightness","label":"Lightness","tooltip":"","order":7,"width":"0","height":"0","passthru":true,"outs":"all","topic":"lightness","topicType":"str","thumbLabel":"true","showTicks":"false","min":0,"max":"100","step":1,"className":"","iconPrepend":"","iconAppend":"","color":"","colorTrack":"","colorThumb":"","x":260,"y":140,"wires":[["61f311a8b5b35e7e"]]},{"id":"44b40de04680b4a9","type":"ui-slider","z":"fbb0a5cd0ab55ab1","g":"f3c5c6ce9c5fae46","group":"74f264f9df3eda4f","name":"Alpha","label":"Alpha","tooltip":"","order":8,"width":"0","height":"0","passthru":true,"outs":"all","topic":"alpha","topicType":"str","thumbLabel":"true","showTicks":"false","min":0,"max":"100","step":1,"className":"","iconPrepend":"","iconAppend":"","color":"","colorTrack":"","colorThumb":"","x":270,"y":180,"wires":[["61f311a8b5b35e7e"]]},{"id":"61f311a8b5b35e7e","type":"join","z":"fbb0a5cd0ab55ab1","g":"f3c5c6ce9c5fae46","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","useparts":false,"accumulate":true,"timeout":"5","count":"4","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":410,"y":120,"wires":[["6608e217685b213a"]]},{"id":"cec6f8cdaf344fb6","type":"inject","z":"fbb0a5cd0ab55ab1","g":"f3c5c6ce9c5fae46","name":"Init","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"Alpha","payload":"88","payloadType":"str","x":110,"y":180,"wires":[["44b40de04680b4a9"]]},{"id":"5d6a97a1565a4bd3","type":"inject","z":"fbb0a5cd0ab55ab1","g":"f3c5c6ce9c5fae46","name":"Init","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"Saturation","payload":"100","payloadType":"str","x":110,"y":100,"wires":[["d312461d30f31272"]]},{"id":"880bdbee13d8a110","type":"inject","z":"fbb0a5cd0ab55ab1","g":"f3c5c6ce9c5fae46","name":"Init","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"Lightness","payload":"80","payloadType":"str","x":110,"y":140,"wires":[["52b62baf3f28e261"]]},{"id":"56012d4b52f8830c","type":"comment","z":"fbb0a5cd0ab55ab1","name":"Every message must include all properties","info":"","x":660,"y":320,"wires":[]},{"id":"aff2b2585a969558","type":"function","z":"fbb0a5cd0ab55ab1","name":"save and pass on","func":"let styles = flow.get(\"styles\") || {}\nstyles[msg.topic] = msg.payload\nmsg.payload = styles\nflow.set(\"styles\", styles)\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":610,"y":280,"wires":[["8f9260ec76e79af3"]]},{"id":"9f79038bb989dbbc","type":"inject","z":"fbb0a5cd0ab55ab1","g":"b8dda7966a82b2a9","name":"Init","props":[{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"str","x":110,"y":280,"wires":[["511c22b45b9c7df4"]]},{"id":"45f4f13e4f7cde29","type":"inject","z":"fbb0a5cd0ab55ab1","g":"475c4ee4351613f0","name":"Init","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"textcolor","payload":"skybluepink","payloadType":"str","x":110,"y":380,"wires":[["a2eb1124d51f64c6"]]},{"id":"41b5f3d452d19958","type":"ui-button","z":"fbb0a5cd0ab55ab1","g":"475c4ee4351613f0","group":"74f264f9df3eda4f","name":"","label":"Red Text","order":3,"width":"1","height":"1","emulateClick":true,"tooltip":"","color":"","bgcolor":"","className":"","icon":"","iconPosition":"left","payload":"red","payloadType":"str","topic":"textcolor","topicType":"str","buttonColor":"","textColor":"","iconColor":"","x":260,"y":420,"wires":[["aff2b2585a969558"]]},{"id":"6bf3ec324642befb","type":"ui-button","z":"fbb0a5cd0ab55ab1","g":"475c4ee4351613f0","group":"74f264f9df3eda4f","name":"","label":"Green Text","order":2,"width":"1","height":"1","emulateClick":false,"tooltip":"","color":"","bgcolor":"","className":"","icon":"","iconPosition":"left","payload":"green","payloadType":"str","topic":"textcolor","topicType":"str","buttonColor":"","textColor":"","iconColor":"","x":270,"y":460,"wires":[["aff2b2585a969558"]]},{"id":"a2eb1124d51f64c6","type":"ui-button","z":"fbb0a5cd0ab55ab1","g":"475c4ee4351613f0","group":"74f264f9df3eda4f","name":"","label":"Black Text","order":4,"width":"1","height":"1","emulateClick":true,"tooltip":"","color":"","bgcolor":"","className":"","icon":"","iconPosition":"left","payload":"skybluepink","payloadType":"str","topic":"textcolor","topicType":"str","buttonColor":"","textColor":"","iconColor":"","x":270,"y":380,"wires":[["aff2b2585a969558"]]},{"id":"d2f6d8d511f82b37","type":"ui-group","name":"Macbeth","page":"2ee3d3a049fdd4c9","width":"7","height":"1","order":1,"showTitle":false,"className":"","visible":"true","disabled":"false"},{"id":"74f264f9df3eda4f","type":"ui-group","name":"CSS Properties","page":"2ee3d3a049fdd4c9","width":"3","height":"1","order":2,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"2ee3d3a049fdd4c9","type":"ui-page","name":"Dynamic CSS in Dashboard 2 ","ui":"d45641ed6d39fea1","path":"/macbeth","icon":"home","layout":"grid","theme":"0d92c765bfad87e6","order":2,"className":"","visible":"true","disabled":"false"},{"id":"d45641ed6d39fea1","type":"ui-base","name":"This is my ui-base","path":"/dashboard","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false,"showPageTitle":true,"navigationStyle":"default","titleBarStyle":"default"},{"id":"0d92c765bfad87e6","type":"ui-theme","name":"Basic Blue Theme","colors":{"surface":"#4d58ff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"},"sizes":{"pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px"}}]
4 Likes

To get it scale down for mobile

From .postit
remove min-height

From .postitinner
remove min-width and min-height
add paddings for all sizes, top wanted to be bigger so maybe padding: 2rem 1.5rem 1.5rem 1.5rem;

For content in .postitinner (h2, p)
font-size: clamp(2rem, 2.75vw, 3rem);
values are as minimum possible, optimal and maximum size. Can have different sizing rules for p and h2

May need some other adjustments but you get the point ..

Nice one :smiley:

1 Like

Those suggestions look good, thanks :grinning:
The desktop page still looks much the same; the postit font sizes are a bit different.
It does look better on my phone although the notepaper divs need attention.

Trouble with CSS is you end up with rules defined and no real idea why they are there.
I think I was originally trying to enforce squareness for the postit note.

That's the point where you have to make compromize decisions and you meet such for almost all designs you can came up.
For resposive designs the golden rule is - content drives the sizes. @media rules (nowdays also container querys) make content and containers to move around, or hide/show if necessary.

1 Like

I'd add that if you've used px sizes anywhere, you probably should rethink. :slight_smile:

Occasionally you might have to but this should very much be the exception (@media breakpoints being one of those). Use rem to relate to the users baseline font size, em to relate to the current font size. % generally for width. fr for grid layouts, vw and vh to relate to the visible window, etc.

I recently discovered cqmin (CSS Container Queries) which has been a huge saver of time in Dashboard. Define a "container" and then the font-size is scaled relative to that container.

Supported by modern (2022+) browsers, except IE11 of course.

Should be taken as strong part of strategy, not just a time saver. That of course is change which is not part of Vue thus can easily put on top of something but has not be taken account in components architecture thus not always straight path to success.
No matter, it is powerful and I'd love to see it more in use.

It does use 2px for the line thickness on the paper, which I decided to allow.

And in the box shadows, which I simply lifted from getcssscan.com (and they lifted from somewhere else).

Finally the curled corner of the postit note is my fault border-bottom-right-radius: 60px 5px; but the curl is subliminal anyway.

Yes, I left those off because how many of us can guarantee the use of browsers from Sept 22 or even Feb 23 for Firefox? I know, for example, that a lot of people use old tablets or phones as Home Automation screens. Personally, I currently try to target early 2019 as my JavaScript version for front-end code as a compromise between newer features and device/browser compatibility.

I wonder actually whether we could come to an agreement about what browser versions to target? That would be a really helpful standard.

We could then also agree for a browser version standard in package.json files.

Every case is unique. If the one needs to do dashboard for an old device, even the DB1 will be challenging. Mostly because of memory issues but as always it depends. Workaround is building it from scratch but that is not related to any of currently available dashboard solutions. Maybe Uibuilder but not necessarily. That makes decision right away easier to make. It just doesn't run smoothly. End of story.

If to hold back with new stuff too long or make everything with fallbacks or with whatever tricks to ensure the thing happen, it takes forever to release anything.

Nothing moves backwards in html/css world. And the tempo is way faster nowadays than it was maybe 10 years ago. Even if some devices survive long enough to see unresolvable content, the time goes in one direction with constant speed. No code can change that.

1 Like