Re-order Divs without access to html - javascript

I'm customising a wordpress theme and have come up against a frustrating blocker.
I would like to position the header (header.non-sticky-nav) after the fullscreen cover (.fullscreen-cover) and before the content (.content).
<header class="non-sticky-nav">
<div id="navbar"></div>
</header>
<div id="wrapper">
<div id="content">
<div class="fullscreen-cover"></div>
<div class="content"></div>
</div>
</div>
current-result_vs_desired-result
I tried repositioning the nav bar by using a "top: xpx" value but obviously that doesn't work as the .fullscreen-cover is not a fixed height.
Here is the test page I am using for the issue: http://samburrough.design/test/
The theme allows page specific or global css code injections, and as theme is regularly updated, I would like to try and stick to using this feature rather than delve into the theme files and have the changes overwritten every time I want to update.
Any help would be hugely appreciated!

Could you not create a child theme and modify the DOM that way?
At least this way the changes won't be over-written every time an update to the parent theme is released?
This would (should) actually be the preferred option.
Smashing Magazine; Create and Customise Wordpress Child Theme

Unfortunately, if the theme does not include block positioning, you need to edit the DOM. While you could probably use some wonky absolute positioning on the bar and the hero, positioning them absolutely is likely to cause you a cascade of problems - starting with the responsive nav.

There is a javascript function/method that lets nodes swap places in the dom.
you could try and look into that Node.replaceChild()
The example below is from the documentation and creates a new element but you can also select an existing node.
// create an empty element node
// without an ID, any attributes, or any content
var sp1 = document.createElement("span");
// give it an id attribute called 'newSpan'
sp1.id = "newSpan";
// create some content for the new element.
var sp1_content = document.createTextNode("new replacement span element.");
// apply that content to the new element
sp1.appendChild(sp1_content);
// build a reference to the existing node to be replaced
var sp2 = document.getElementById("childSpan");
var parentDiv = sp2.parentNode;
// replace existing node sp2 with the new span element sp1
parentDiv.replaceChild(sp1, sp2);

You could try using order with flexbox. For example:
.container {
display: flex;
flex-wrap: wrap;
}
.one,
.two {
width: 100%;
}
.one {
order: 2;
background: red;
}
.two {
order: 1;
background: blue;
}
<div class="container">
<div class="one">
1
</div>
<div class="two">
2
</div>
</div>
Might be a bit problematic, depending on what your markup looks like. And won't work on older browsers.

Related

Adding HTML via JS to a specific child-Element

I have a very specific situation where I have ~50 child-divs which I cannot influence directly, that is, I cannot add classes or ids to one specific child-div nor alter the div via HTML because they are created automatically.
They appear in a simple grid/flexbox, two boxes next to each other. I already altered some of them with nth-child, but now I want to add individual headlines between f.ex. div 30 and 31.
Up until now, when I wanted some of the fields to be bigger, I addressed one of the child-divs directly via nth-child.
Here's the basic structure:
<div class="parent">
{$content} // basically <div>{$single-box-content}</div>
</div>
And the CSS I currently use:
.parent {
width: 800px;
display: flex;
gap: 20px;
flex-wrap: wrap;
}
.parent:nth-child(10) {
width:800px;
}
That worked quite well. However, now that I want to have a headline above one of the divs (not inside), it doesn't work. When I try this:
.parent:nth-child(31):before {
content: "Headline";
display: block;
}
It appears inside the child-div, not above it. I cannot add a div to the HTML part, since all of them are created automatically in the backend (it's a form).
I wondered if it is possible to use JavaScript with some element.innerHTML, but I am at the very beginning of learning JS and I couldn't find anything (I could adapt) to address specific child-Elements in JS.
Is there a frontend solution to my problem?
With JS you can add classes, IDs, append HTML-elements to the DOM and so much more.
Below shows you how to both to insert an h2, but also how to add a class to an element of your choosing - I used :nth-child(3) for illustration purposes, but you can just swap that with :nth-child(31). The code is explained in comments in the snippet.
// finding the child element with nth-child selector
let selected = document.querySelector('.parent:nth-child(3)');
// giving it a class name
selected.classList.add('parentClass');
// creating a h2 element
let header = document.createElement("h2");
// the text inside the h2 element
let headerText = document.createTextNode("headline");
// appending the text to the h2 element
header.append(headerText);
// giving the child a class name
header.classList.add('childClass');
// appending the headline above/before the selected element
selected.parentNode.insertBefore(header, selected);
/* the class applied with JS */
.parentClass {
background-color: red;
}
.childClass {
background-color: limegreen;
}
<div class="parent">parent 1</div>
<div class="parent">parent 2</div>
<div class="parent">parent 3</div>

Hiding just some overflow content

Structure:
<div id="content">
<div id="contentTitle" class="ParentCollapser FancyTitle">title</div>
<br />
some text
</div>
After the document loads, I have a js script that looks up all elements with "ParentCollapser" and attatches click driven functions to them that allow the user to collapse the parent when clicked (sets height to 0 right now).
The clicking action works great except for some styling issues - .FancyTitle is defined as such:
.FancyTitle{
margin-left:-40px;
margin-right:-40px;
margin-top:-20px;
margin-bottom:10px;
}
So basically it reaches outside the parent container by 20px on left/top/right. To hide the content, when collapsed i had to set the #content overflow:hidden but that also hides the parts of #contentTitle that reach outside and that looks like poo.
Is there any kind of exception that I can define for the title so it wouldn't be hidden no matter what? Other option would be to make structure alterations but I'd like to avoid that if possible since right now its super easy to use.
You could try fiddling with the negation CSS pseudo class not() with an appropriate selector. Example:
#content:not(#contentTitle) {
overflow:hidden;
}
CSS negation pseudo class
Just be mindful of browser compatibility.
Since the title should be shown all time there is no idea to hide it's parent. Therefore I added a child with the content in.
HTML
<div style="padding:100px;background:gray">
<div id="content" style="background:blue">
<div id="contentTitle" class="ParentCollapser FancyTitle">title</div>
<div class="contentChild">some text</div>
</div>
</div>
Now we hide the contentChild with js
JavaScript
this.Collapse = function() {
this.parent.querySelector("div.contentChild").style.display = "none";
this.collapsed = true;
};
this.UnCollapse = function() {
this.parent.querySelector("div.contentChild").style.display = "block";
this.collapsed = false;
};
Demo

ExtJS 4.2: Div inside span tag when layout=auto

I am trying to understand the reason behind doing this.
<fieldset id="fieldset-1015" class="x-fieldset x-fieldset-with-title x-fieldset-with-header x-fieldset-default" style="border-width:0;">
<legend id="fieldset-1015-legend" class="x-fieldset-header x-fieldset-header-default">
<div id="fieldset-1015-body" class="x-fieldset-body ">
<span id="fieldset-1015-outerCt" style="display: table; width: 100%; table-layout: fixed;">
<div id="fieldset-1015-innerCt" class="" style="display:table-cell;height:100%;vertical-align:top;">
</div>
</span>
</div>
</fieldset>
I know this a very debatable question. But I want to understand why ExtJS chose to do it this way for their layouts.
I don't see divs inside span in other layout like layout=container
Block elements inside inline elements is discussed in these questions(and many more) -
can tags have any type of tags inside them?
Is putting a div inside an anchor ever correct?
Answer for your question is in comment in code (source: http://cdn.sencha.io/ext-4.2.0-gpl/ext-all-debug-w-comments.js):
// All browsers that support display:table use this template.
// An outerCt with display:table shrink-wraps contents, and contains child
// margins. The table-cell innerCt is required in order to support percentage
// heights on child elements. Originally the outerCt started out as a div, but
// was changed to a span to work around an obscure firefox 3.6 bug where
// placing a Container inside of a fieldset's legend element causes the legend
// to blow up if the outerCt is a div.

Performance of adding CSS class & number of children

I need to dynamically apply some styling to elements .child-1 and .child-2 by adding CSS classes.
Should I add them once to #parent or to each .child-? If I add it to #parent would existence of #large-container affect the performance?
<div id="parent">
<div class="child-1"></div>
<div class="child-2"></div>
<div id="large-container">
<!-- a bunch of content here - p tags, images... -->
</div>
</div>
(.child-1 and .child-2 are absolute positioned elements on top of #large-container)
$('#parent').addClass('myClass1 myClass2');
vs
$('.child-1, .child2').addClass('myClass1 myClass2');
Same with just CSS:
.myClass1 .child-1,
.myClass2 .child-2 {
color: red;
}
/* vs */
.myClass1.child-1,
.myClass2.child-2 {
color: blue;
}
myClass1 myClass2 only apply styles to #child-1 and 2, they don't add any styles to #large-container.
Thank you for advice!
although i think my answer is impossible to verify from a profiler (are there any css/html profiling tools out there in terms of rendering the page etc?) I'll state it based on my experience:
$('#parent').addClass('myClass1 myClass2');
is faster than
$('#child-1, #child2').addClass('myClass1 myClass2');
simply because you are traversing the dom tree once rather than twice ie
$('#child-1, #child2').addClass('myClass1 myClass2'); is the same as
$('#child-1).addClass('myClass1 myClass2');
$('#child-1).addClass('myClass1 myClass2');
to theoretically prove that last point imagine your html code looked something like this:
<div id="parent">
<div id="child-1"></div>
... lots and lots of html nodes
<div id="child-2"></div>
</div>
then looking for #child-1 is a completely separate operation than looking for #child-2.. and when it comes to css/html optimisation.. one of the most expensive operations is the DOM tree traversal.
in the case of $('#parent').addClass('myClass1 myClass2'); you are traversing the DOM tree once (ie finding where #parent is then using css cascading to apply to the elements within the narrowed down #parent DOM subtree
to address the concern that #tMagwell raised about repainting #large-container here is another optimized way of applying css:
// store the child-1 node in a variable.. ie whenever you
// refer to it in the future.. you won't have to traverse the entire DOM again
var child1element = $('#child-1');
$('#child-1).addClass('myClass1 myClass2');
// referring to child1element costs you nothing big, it's already stored in a variable
child1element.siblings().addClass('myClass1 myClass2');
this code works of course assuming that there are only child-1 and child-2.. if you got child-3, child-4.. child-n and only want to apply it to child-n.. then you can use
child1element.siblings()[n] // where n is the index of the child you want to target, since siblings() returns an array
hope this helps!
update:
to address this specific point you raised in the comments:
Does the presence of #large-container slows down something when I add classes to #parent?
the answer is yes. let me give you a scenario where it definitely does:
css:
#parent .class1 .class2
{
font-size:10pt;
}
html:
<div id="parent">
<div id="child-1"></div>
<div id="child-2"></div>
<div id="large-container">
<!-- images etc -->
<p>hello world!<p>
<!-- many more p tags that has a lot of text and stuff -->
</div>
</div>
so in this example.. the font-size:10pt placed under #parent .class1 .class2 will definitely impact the contents of #large-container.. and the operation costs something.. i have no way to quantify how expensive that is (it would depend on the browser rendering engine etc).. but suffice it to say that there is some cost x that is higher than if you didn't just add class1 and class2 to the parent div.

Show just particular parts of website - select via CSS?

what would be the easiest method to display only specific elements on a website?
For example, on a news site only the headlines and nothing else.
I'd like to select elements via CSS so only those should be displayed.
I tried to use the :not pseudoclass:
:not(.myClass) { display: none; }
But obviously, the parents of the .myClass-elements aren't displayed and so aren't them.
Do you know any possibility to achieve this? It doesn't have to be CSS-only, Javascript is possible too.
A web-app that does this would also be great.
I'd like to be able to filter some sites I visit, so I would apply this as a user-stylesheet.
You can load the page with jQuery and easily select the elements you want...
$("body").load("path/to/page.html div.headline");
The above will load all <div class="headline"> elements into the body of the document.
Note: You will of course have to keep the same origin policy in mind.
If you want to show only the news headline you will need to structure your HTML correctly. If you have a container div the easiest way to do this would be to apply a secondary class to it and show/hide elements trough that class:
<div class="container news_page">
<h1>Title</h1>
<p>Random text I want to hide.<p>
<div class="random_container">Another random element i want to hide.</div>
</div>
.container {border:1px solid red;} /* .container has normal styling */
.news_page p, .news_page .random_container {display:none;} /* .news_page is used only to select elements inside container on news page */
This would be the css only solution to this.
I can't figure out how to comment on things, so as a response to the last answer's last comment, check this out: http://selectivizr.com/. It says it can emulate CSS3 selectors for IE, so maybe that will fix your problems with Exploder...

Categories