Skip to content
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

EthicalAds: Default to fixedfooter for smaller screens #447

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
52 changes: 2 additions & 50 deletions src/ethicalads.css
Original file line number Diff line number Diff line change
Expand Up @@ -128,56 +128,8 @@ div.ethical-footer {
font-size: 10px;
}

/* Fixed footer promotions */
.ethical-fixedfooter {
box-sizing: border-box;
position: fixed;
bottom: 0;
left: 0;
z-index: 100;
background-color: #eee;
border-top: 1px solid #bfbfbf;
font-size: 12px;
line-height: 1.5;
padding: 0.5em 1.5em;
text-align: center;
color: #404040;
width: 100%; /* Fallback for Opera Mini */
width: 100vw;
}
@media (min-width: 769px) {
/* Improve viewing on non-mobile */
.ethical-fixedfooter {
font-size: 13px;
padding: 1em 1.5em;
}
}
.ethical-fixedfooter .ethical-text:before {
margin-right: 4px;
padding: 2px 6px;
border-radius: 3px;
background-color: #4caf50;
color: #fff;
content: "Sponsored";
}
.ethical-fixedfooter .ethical-callout {
color: #999;
padding-left: 6px;
white-space: nowrap;
}
.ethical-fixedfooter a,
.ethical-fixedfooter a:hover,
.ethical-fixedfooter a:active,
.ethical-fixedfooter a:visited {
color: #404040;
text-decoration: none;
}
.ethical-fixedfooter .ethical-close {
position: absolute;
top: 0;
right: 5px;
font-size: 20px;
line-height: 20px;
.ethical-fixedfooter-margin {
margin-bottom: 5em;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@agjohnson Is there a way to have this match the height of the ad instead of a random height?

Seems like you could hack it with something like:

// Get the height of the target element
const targetElement = document.querySelector('.target-class');
const matchingElement = document.querySelector('.matching-class');

// Match the height dynamically
matchingElement.style.height = `${targetElement.offsetHeight}px`;

but I don't think there's a way to do it non-dynamically, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even calculating the margin at load time, it will break when resizing the window.

I think the problem here is position: fixed (that comes from EthicalAd client CSS). Using a more selector with more specificity (😉 @agjohnson ) we can override it. Example showing how it works:

#readthedocs-ea {
  position: static;
}

With this, we don't need to add the extra class .ethical-fixedfooter-margin to all the elements as you are doing in https://github.com/readthedocs/addons/pull/447/files#diff-10e47ee23788d0e8d3d4e13cee726fd04c8fe035922a74ac1c7d432db1dfb9faR191

I understand this works because we are adding this element as the last one in the document.body.

However, it does not work well in all the documentation tools because the ad may end behind a scroll 😞

Demo

Material for MkDocs

Peek 2025-01-15 10-51

Sphinx Furo

Peek 2025-01-15 10-58

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There isn't pure CSS solution here given the fixed footer is a separate element from the elements you're adding classes to for the margin -- there isn't a way to reference between elements like this unless one element is a direct descendant. In this case you have more options and calc() might be able to get there.

I'd avoid a JS solution here especially using Element.style -- my note above applies here.

It feels like we should have multiple explicit styles by viewport size, not necessarily try to do this dynamically -- that is we'd have explicit heights for mobile, table, desktop widths.

}

/* RTD Theme specific customizations */
Expand Down
47 changes: 40 additions & 7 deletions src/ethicalads.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,41 @@ export class EthicalAdsAddon extends AddonBase {
if (elementToAppend) {
elementToAppend.append(placement);
}
} else if (window.innerWidth > 1300) {
// https://ethical-ad-client.readthedocs.io/en/latest/#stickybox
placement.setAttribute("data-ea-type", "image");
placement.setAttribute("data-ea-style", "stickybox");
this.addEaPlacementToElement(placement);
// `document.body` here is not too much relevant, since we are going to
// use this selector only for a floating stickybox ad

// Try fixed footer instead of stickybox as a default experience

// } else if (window.innerWidth > 1300) {
// // https://ethical-ad-client.readthedocs.io/en/latest/#stickybox
// placement.setAttribute("data-ea-type", "image");
// placement.setAttribute("data-ea-style", "stickybox");
// this.addEaPlacementToElement(placement);
// // `document.body` here is not too much relevant, since we are going to
// // use this selector only for a floating stickybox ad
// const elementInsertBefore = document.body;
// elementInsertBefore.insertBefore(
// placement,
// elementInsertBefore.lastChild,
// );
} else if (window.innerWidth > 768) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a case for matchMedia: https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia

Noted earlier that this check isn't dynamic currently, it's only evaluated once. Using matchMedia as an event gives a way to do this after page load.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't easily reconfigure the ad without doing another API call, so we don't want it to be dynamic. We want to have a single ad load on page load, and stick with that, otherwise it will get weird.

// Use fixed footer for smaller widths, but not mobile
// https://ethical-ad-client.readthedocs.io/en/latest/#fixedfooter
placement.setAttribute("data-ea-type", "text");
placement.setAttribute("data-ea-style", "fixedfooter");
placement.classList.add("ethical-fixedfooter");

// Add margin to content and footers to avoid hiding content
const root_node = document.querySelector(docTool.getRootSelector());
const footers = document.querySelectorAll("footer, .footer");

if (root_node) {
root_node.classList.add("ethical-fixedfooter-margin");
}

footers.forEach((footer) => {
footer.classList.add("ethical-fixedfooter-margin");
});
Comment on lines +183 to +193
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could end up adding a lot of extra space at the bottom depending on the number of elements the page has.

Using stickybox

Screenshot_2025-01-15_11-03-26

Using fixedfooter

Screenshot_2025-01-15_11-03-39

Copy link
Contributor

@agjohnson agjohnson Jan 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd need to be a lot more precise adding margins into user content like this. Adding margin into the main document content is probably not what we want either, as there isn't a direct link between the main document content and the bottom of the frame.

I suppose I'm not convinced we should be adding margins into nested elements yet. document.body is probably the place we should be adding padding (body { padding-bottom: 1rem; }) for a fixed footer, but not where we should insert an ad placement.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we just not try and just the bottom margins at all? The issue is that it covers up fixed position content on other themes (eg. mkdocs-material), so I wasn't sure what the right approach was.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I had to choose, I would prefer to cover footer content than breaking layout (adding weird margins). In either case, we can work on "better placement for that particular doctool" when we see it or when users complain 😄

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, I was trying to build a better placement for mkdocs-material specifically, because I know that's one we want to support, so understanding the "right" way to bump the ad above the footer is still useful. I agree maybe we just add that to the theme-specific support?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have a specific positioning for Material for MkDocs that's working already: https://docs.pypi.org/

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, but not for smaller screen sizes, like we are discussing?


// Inject the actual ad
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems than depending on the theme/doctool the may be injected in a weird place and not covering the full width:

Solidity

Screenshot_2025-01-15_11-10-41

Our docs

Screenshot_2025-01-15_11-10-20

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, my comment above was about not adding the fixed footer to document.body, but this feels like we should be adding the fixed footer placement to document.body. Do we want it full width of the frame or not?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want it full width of the frame or not?

I think it should be full width, yes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It shouldn't be showing on the RTD theme, since that has a custom placement. I'm not really sure what the change being suggested here is -- isn't the ad getting injected into the document.body?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ad is being injected on RTD theme here. I think that happens because of the current logic: "if the specific placement it not above the fold, we show the default placement". The "default placement" now is fixedfooter, and that's why it's being shown.

const elementInsertBefore = document.body;
elementInsertBefore.insertBefore(
placement,
Expand Down Expand Up @@ -201,6 +229,11 @@ export class EthicalAdsAddon extends AddonBase {
}

elementAboveTheFold(element) {
// Return false if element doesn't exist
if (!element) {
return false;
}

// Determine if this element would be above the fold.
// If this is off screen, instead create an ad in the footer.
// Assumes the ad would be AD_SIZE pixels high.
Expand Down