-
Notifications
You must be signed in to change notification settings - Fork 116
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
Support pseudoelements #20
Comments
Getting styles for these pseudo elements, and checking if they exist in the first place, boils down to this: |
Is it the only way to add real element from 'pseudo' to a document? This code is 'after, before' to span. const css = '.before-reset::before, .after-reset::after { content: none !important; }';
const head = document.head || document.getElementsByTagName('head')[0];
const style = document.createElement('style');
style.type = 'text/css';
style.appendChild(document.createTextNode(css));
head.appendChild(style);
const allElements = document.getElementsByTagName('*');
for (let i = 0; i < allElements.length; i++) {
const elementBeforeStyles = window.getComputedStyle(allElements[i], ':before');
const elementAfterStyles = window.getComputedStyle(allElements[i], ':after');
const elementBeforeContent = elementBeforeStyles.content;
const elementAfterContent = elementAfterStyles.content;
if (elementBeforeContent) {
const virtualBefore = document.createElement('span');
virtualBefore.setAttribute('style', elementBeforeStyles.cssText);
virtualBefore.innerHTML = elementBeforeStyles.content.split('"').join('');
allElements[i].className += ' before-reset';
allElements[i].prepend(virtualBefore);
}
if (elementAfterContent) {
const virtualAfter = document.createElement('span');
virtualAfter.setAttribute('style', elementAfterStyles.cssText);
virtualAfter.innerHTML = elementAfterStyles.content.split('"').join('');
allElements[i].className += ' after-reset';
allElements[i].appendChild(virtualAfter);
}
} When I run it, 'clearfix' using 'display: table;' causes problems. |
@KimDal-hyeong we might be able to see if something is hidden or not based on what we get back from
Or it might be I am missing something? I think you people are right the limitations of using |
As far as I understand @KimDal-hyeong idea and code, we can replace pseudoelements with "real" elements and continue business as usual. I think this is a really neat workaround 👏, but probably not something solid enough to put into html-sketchapp. I think we should be able to figure out position from CSS props, but this will be tricky. |
StatusWithout WorkaroundMeanwhile @KimDal-hyeong hack that replaces pseudo-elements with spans is the way to go. |
@ryanseddon yeah, in DT it's possible through the DevTools debugging protocol, but html-asketch currently runs in a browser context, so we don't have access to that. It's possible that we will move generating asketch files to puppeteer in the future (where we have access to the protocol and can do a lot of cool stuff), but I wanted to avoid hard dependencies on puppeteer/chrome/DT protocol until it's absolutely needed. [EDIT] for anyone interested (or future me):
|
Is this in active development somewhere? From the thread above I'm not sure if the recommended approach is using the |
@calebdwilliams definitely the |
@KimDal-hyeong thank you for your script. I needed to modify your script with the following changes to get it work for me: - const allElements = document.getElementsByTagName('*');
+ const allElements = document.querySelectorAll('body *'); - if (elementBeforeContent) {
+ if (elementBeforeContent && elementBeforeContent !== 'none') { - if (elementAfterContent) {
+ if (elementAfterContent && elementAfterContent !== 'none') { maybe you can update it with this changes to make it for others easier to use it. |
I got some code working right now based on the // Convert placeholder into span
const generatePlaceholderElement = (el) => {
if (el.nodeName !== 'INPUT' || el.nodeName !== 'TEXTAREA') return;
if (!el.hasAttribute('placeholder')) return;
// Emulation of placeholders
const elementPlaceholderStyles = window.getComputedStyle(el, ':placeholder');
const virtualPlaceholder = document.createElement('span');
virtualPlaceholder.className += 'virtual-placeholder';
virtualPlaceholder.innerHTML = el.getAttribute('placeholder');
virtualPlaceholder.style.position = "absolute";
virtualPlaceholder.style.color = elementPlaceholderStyles.color;
virtualPlaceholder.style.lineHeight = elementPlaceholderStyles.lineHeight;
virtualPlaceholder.style.top = (parseInt(elementPlaceholderStyles.borderTopWidth.replace(/px/,'')) + parseInt(elementPlaceholderStyles.paddingTop.replace(/px/,'')) + 'px');
virtualPlaceholder.style.left = (parseInt(elementPlaceholderStyles.borderLeftWidth.replace(/px/,'')) + parseInt(elementPlaceholderStyles.paddingLeft.replace(/px/,'')) + 'px');
// Remove Placeholder and set positioning for parent
el.removeAttribute('placeholder');
let target = el.parentElement;
if (target.firstChild != el) {
var wrapper = document.createElement('div');
wrapper.className += 'virtual-wrapper';
target.insertBefore(wrapper, el);
wrapper.appendChild(el);
target = wrapper;
}
target.style.position = "relative";
target.appendChild(virtualPlaceholder);
}
// Convert Input Value into span
const generateInputValueElement = (el) => {
if (el.nodeName !== 'INPUT' || !el.hasAttribute('value')) return;
const elementValueStyles = window.getComputedStyle(el);
const virtualValue = document.createElement('span');
virtualValue.className += 'virtual-value';
virtualValue.innerHTML = el.getAttribute('value');
virtualValue.style.position = "absolute";
virtualValue.style.color = elementValueStyles.color;
virtualValue.style.lineHeight = elementValueStyles.lineHeight;
virtualValue.style.top = (parseInt(elementValueStyles.borderTopWidth.replace(/px/,'')) + parseInt(elementValueStyles.paddingTop.replace(/px/,'')) + 'px');
virtualValue.style.left = (parseInt(elementValueStyles.borderLeftWidth.replace(/px/,'')) + parseInt(elementValueStyles.paddingLeft.replace(/px/,'')) + 'px');
// Remove Value and set positioning for parent
el.value = '';
el.parentElement.style.position = "relative";
el.parentElement.appendChild(virtualValue);
}
// Convert Input Value into span
const generateTextareaValueElement = (el) => {
if (el.nodeName !== 'TEXTAREA' || !el.innerHTML) return;
const elementValueStyles = window.getComputedStyle(el);
const virtualValue = document.createElement('span');
virtualValue.className += 'virtual-value';
virtualValue.innerHTML = el.innerHTML;
virtualValue.style.position = "absolute";
virtualValue.style.color = elementValueStyles.color;
virtualValue.style.lineHeight = elementValueStyles.lineHeight;
virtualValue.style.top = (parseInt(elementValueStyles.borderTopWidth.replace(/px/,'')) + parseInt(elementValueStyles.paddingTop.replace(/px/,'')) + 'px');
virtualValue.style.left = (parseInt(elementValueStyles.borderLeftWidth.replace(/px/,'')) + parseInt(elementValueStyles.paddingLeft.replace(/px/,'')) + 'px');
// Remove Value and set positioning for parent
el.value = '';
el.innerHTML = '';
let target = el.parentElement;
if (target.firstChild != el) {
var wrapper = document.createElement('div');
wrapper.className += 'virtual-wrapper';
target.insertBefore(wrapper, el);
wrapper.appendChild(el);
target = wrapper;
}
target.style.position = "relative";
target.appendChild(virtualValue);
}
I also had to wrap the elements so that absolute positioning would work reliably. |
@KimDal-hyeong @alexander-schranz where exactly should i put that code? EDIT: I was using story2sketch and was a little confused. The following updated scripts pseudoelements with different colors at different breakpoints const fixPseudoElements = () => {
const css = '.before-reset::before, .after-reset::after { content: none !important; }';
const head = document.head || document.getElementsByTagName('head')[0];
const style = document.createElement('style');
style.type = 'text/css';
style.appendChild(document.createTextNode(css));
head.appendChild(style);
const allElements = document.querySelectorAll('body *');
const oldFakes = document.querySelectorAll('body .fake-pseudo');
if (oldFakes) {
Array.from(oldFakes).map(el => el.remove())
}
for (let i = 0; i < allElements.length; i++) {
allElements[i].className = allElements[i].className.replace('before-reset', '')
allElements[i].className = allElements[i].className.replace('after-reset', '')
const elementBeforeStyles = window.getComputedStyle(allElements[i], ':before');
const elementAfterStyles = window.getComputedStyle(allElements[i], ':after');
const elementBeforeContent = elementBeforeStyles.content;
const elementAfterContent = elementAfterStyles.content;
if (elementBeforeContent && elementBeforeContent !== 'none') {
const virtualBefore = document.createElement('span');
virtualBefore.className = "fake-pseudo"
virtualBefore.setAttribute('style', elementBeforeStyles.cssText);
virtualBefore.innerHTML = elementBeforeStyles.content.split('"').join('');
allElements[i].className += ' before-reset';
allElements[i].prepend(virtualBefore);
}
if (elementAfterContent && elementAfterContent !== 'none') {
const virtualAfter = document.createElement('span');
virtualBefore.className = "fake-pseudo"
virtualAfter.setAttribute('style', elementAfterStyles.cssText);
virtualAfter.innerHTML = elementAfterStyles.content.split('"').join('');
allElements[i].className += ' after-reset';
allElements[i].appendChild(virtualAfter);
}
}
} |
It would be nice to build in support for before and after elements.
The text was updated successfully, but these errors were encountered: