eqcss / eqcss

EQCSS is a CSS Reprocessor that introduces Element Queries, Scoped CSS, a Parent selector, and responsive JavaScript to all browsers IE8 and up

Home Page:https://elementqueries.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

use $parent height in a rule?

matthewjumpsoffbuildings opened this issue · comments

Is there currently a way with EQCSS to use the dimensions of the parent node in calculations? eg something like this:

@element '.item' {
  $this {
    height: eval('parent.height*2');
  }
}

Hey @matthewjumpsoffbuildings! Youre right, and so close! Try eval('parentNode.offsetHeight * 2') here! Everything inside eval('') is vanilla JavaScript, so you can look up the various ways to measure things for regular JS and use them here, just remenber that you're always running them from the context of the scoped selector, in your case from the perspective of the .item elements :)

holy crap that is so good! why have i never heard of this before?

btw, can you access any JS vars in the global scope in the evals? for example jquery stuff?

Yes, any variables in the global scope can be used directly, you can write any JS one-liners and evaluate them right in-line, or even call functions and use what they return in your CSS.

You are also able to use this anywhere inside an @element query, so you can use it in values, as part of propeties, in selectors...

There are a bunch of examples on Codepen, search for EQCSS and look for uses of eval for ideas of what you can do <3

can you use CSS units in the evals? im guessing no, but if you somehow already support eval(100vh+50px) im gonna crap my pants

You cant use css units in eval, but since you can use eval anywhere you can use eval inside calc just fine, like calc(100px + eval(‘innerWidth/2')px) would evaluate to calc(100px + 500px) if your browser is 1000px wide, because eval('innerWidth/2') is going to evaluate to 500.

Does that make sense?

i love you

final question - i assume the css rules are also applied to new elements added to the DOM via JS? eg if you are doing ajax page loads etc?

edit - oh and also does it clean up/garbage collect listeners etc on DOM elements if they are removed from the DOM?

final question - i assume the css rules are also applied to new elements added to the DOM via JS? eg if you are doing ajax page loads etc?

Yes, If you add elements to the DOM in a way that doesn't naturally trigger an EQCSS recalculation you're always able to call EQCSS.apply() (and EQCSS.throttle()) from JavaScript. If you have an AJAX page load or HTML being added to your page (like a modal being created from a template) you can usually call EQCSS.apply() directly after the code that adds the HTML and it should apply.

There is also EQCSS.load() and EQCSS.parse() if you're adding new styles after the page has loaded that you want EQCSS to become aware of.

I've built a little example here of a demo where there are @element queries, but not HTML on the page at the time the page loads for them to apply to. Then, every 2000ms I will randomly pick a <template> tag an add its HTML to the page. In theory, this should mimic the type of situation you're talking about. In my demo I've included EQCSS.apply() right after the HTML gets added to the page so you can see the ideal location of it - but try commenting it out and seeing how EQCSS doesn't immediately apply to the new elements unless you do something on the page to trigger a recalculation, like clicking, typing, resizing the window, etc.

<div id=mount></div>

<template id=option1>
  <h1>Option 1</h1>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit</p>
</template>

<template id=option2>
  <h2>Option 2</h2>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit</p>
</template>

<style>
  @element 'h1' {
    $this { background: lime; }
  }
  @element 'h2' {
    $this { background: purple; }
  }
  @element 'p' {
    $this { background: blue; }
  }
</style>

<script>
  // Perform this every 2 seconds
  var pageLoad = setInterval(function(){

    // Pick a random option between #option1 and #option2
    var option = Math.random() < .5 ? '#option1' : '#option2'

    // Find the template tag
    var template = document.querySelector(option)

    // Locate where we want to mount the HTML
    var mount = document.querySelector('#mount')

    // Populate monut point with our templated HTML
    mount.innerHTML = template.innerHTML

    // Recalculate EQCSS after new HTML is present
    EQCSS.apply()

  },2000)
</script>

<script src=http://staticresource.com/eqcss/EQCSS.js></script>

You can learn more about how you can manually control EQCSS via JavaScript here: https://github.com/eqcss/eqcss/wiki/Understanding-EQCSS-Triggers

oh and also does it clean up/garbage collect listeners etc on DOM elements if they are removed from the DOM?

I don't think so, but there wouldn't be very much of this. I'll highlight the sections in EQCSS.js where the event listeners are added, there are only two places:

At the end of the file we set most of our event listeners on window: https://github.com/eqcss/eqcss/blob/gh-pages/EQCSS.js#L953&L973

The exception to that is for our scroll-based queries: min-scroll-x, max-scroll-x, min-scroll-y, max-scroll-y - those will either be added to the <html> and <body> elements if you're watching the whole page scroll, or to any individual element you write a query for. The code for that is here for min-scroll-x: https://github.com/eqcss/eqcss/blob/gh-pages/EQCSS.js#L433&L445 and repeated 3 times below that for the other scroll conditions.

If your HTML included an element like <div class=holder></div> and you had written a rule like @element '.holder' and (min-scroll-y: 1px) { $this { background: lime; } } it would result in an event listener being added to any .holder element on our page, and there is nothing in EQCSS that would remove or cancel this event listener at any later time.

So 'no' it doesn't clean up automatically, but it's not very messy either. Do you have any ideas on how to improve this aspect of it?

ok thanks for the incredibly in depth response, makes sense

i dont have any suggestions off the top of my head but i will get back to you after using it in a project for a bit