// caching the document in a variable with a shorter name (because I'm lazy, and
// don't like typing unnecessarily):
const doc = document,
// a simple function to create and append an element, taking four
// arguments:
// what: String, the element-type you wish to create,
// where: String, a CSS selector to find the element to which the created-
// element should be appended,
// fn: function, the callback function to fire once the element is loaded,
// props: Object, properties and property-values to apply to the created-
// element, with a default value of an empty Object literal:
appendElementTo = (what, where, fn, props = {}) => {
// using document.createElement() to create the desired element,
// passing that created-element along with the props Object to
// Object.assign() to add the given properties (if any)
let creation = Object.assign(doc.createElement(what), props),
// using document.querySelector() to retrieve the element to which
// the created-element should be appended; this will return the first
// matching element from the document (if such an element exists), or
// null (if not matching element exists):
target = doc.querySelector(where);
// here we check that the target element exists, and use a Yoda condtion to
// check that the target.nodeType is 1 (and is therefore an HTMLElement),
// I use the Yoda condition because it's almost impossible to accidentally
// use an assignment in place of a comparison:
if (target && 1 === target.nodeType) {
// if there is a callback function supplied:
if (fn) {
// we use EventTarget.addEventListener() to bind the callback function
// aas the 'load' event-listener on the created-element:
creation.addEventListener('load', fn);
}
// we use Element.append() to append the created-element to the
// target element:
target.append(creation);
}
// this function returns nothing to the calling context, you may wish to
// add an explicit return in your use-case (but that's beyond the scope
// of the current question).
},
// a simple function to demonstrate the callback working (this can be more
// or less complex as you require to achieve your desired functionality):
test = (evt) => {
document.querySelector('body p:last-child').style.color = `red`
};
// calling the function, passing in the Strings
// 'link' and 'head' (the 'what' and 'where' arguments respectively):
appendElementTo('link', 'head',
// passing in a reference to the callback function (note the
// deliberate lack of parentheses):
test,
// and, finally, an Object literal for the properties to apply to the created element:
{
// the element-property as the Object keys, and the element property-values
// as the Object values (the search paramater and calls to Math.random() are to cause
// the browser to load the resource on every run, rather than caching (in your own
// use-case this may not be required, adjust to taste):
href: `https://davidrhysthomas.co.uk/linked/base.css?v=${Math.random()}.${Math.random()}`,
type: `text/css`,
rel: `stylesheet`,
});
<main>
<h2>Demo content</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus repellendus, eos itaque ab doloremque dolorum reiciendis ut, unde commodi. Esse, voluptatem dolorem sint ratione placeat quas, inventore non autem ullam aperiam quae minima eaque nobis
eos. Voluptatum sunt perspiciatis ab illum tempora quam, odio voluptatem ipsam eaque amet, cumque animi aut, facilis quidem nihil quasi, vel rerum quaerat numquam vero deserunt earum ipsum. Voluptatem atque, quas provident. Voluptatum, expedita consequatur
modi voluptate reiciendis, consequuntur nostrum laboriosam itaque suscipit magni dolorem maxime cumque unde facere, culpa animi, corporis nam necessitatibus? Nesciunt impedit aliquam molestias quos, consequatur, neque ad architecto quibusdam laborum
optio dolores!</p>
<p>Provident, voluptatum. Optio ut officiis nam ex debitis officia animi placeat dolorum inventore ipsa sapiente illum numquam doloremque assumenda libero a impedit laboriosam, ratione eveniet expedita, voluptates nihil est, perspiciatis. Nostrum magnam
possimus fugiat dolor, quod repellat beatae porro? Delectus eaque minima facilis autem temporibus fugiat numquam impedit nisi aspernatur cupiditate reiciendis corporis, placeat totam, ipsa, commodi aut. Quam porro ratione dolor sunt est dicta sapiente
molestiae adipisci eveniet dolorum assumenda pariatur deserunt vitae officiis, rem nostrum in recusandae doloremque repellat odit voluptatum, aperiam necessitatibus. Quia consectetur quod doloribus esse, tempore iusto, vel culpa ut, consequatur quas
odit.
</p>
</main>